<!--   ***********  Web Authentication - Level 3 - Spec source file ***********
Notes:
* the h1 tag is spec title that is rendered within the document window. Wrapping
  may be controlled with break tags.  The spec 'Level' value is not appended.
* the Title metadata value is what is rendered in the browser's title bar, any break
  tags will be rendered. It also has the spec 'Level' value (gratuitously) appended.
-->

<h1>Web Authentication:<br>An API for accessing Public Key Credentials<br>Level 3</h1>
<pre class='metadata'>
Title: Web Authentication: An API for accessing Public Key Credentials - Level 3
Status: ED
Prepare for TR: true
TR: https://www.w3.org/TR/webauthn-3/
ED: https://w3c.github.io/webauthn/
Previous Version: https://www.w3.org/TR/2021/REC-webauthn-2-20210408/
Previous Version: https://www.w3.org/TR/2019/REC-webauthn-1-20190304/
Shortname: webauthn
Level: 3
Include MDN Panels: maybe
Editor: Tim Cappalli, w3cid 111190, Okta, tim.cappalli@okta.com
Editor: Michael B. Jones, w3cid 38745, Self-Issued Consulting, michael_b_jones@hotmail.com
Editor: Akshay Kumar, w3cid 99318, Microsoft, akshayku@microsoft.com
Editor: Emil Lundberg, w3cid 102508, Yubico, emil@yubico.com
Editor: Matthew Miller, w3cid 129314, Cisco, mattmil3@cisco.com
Former Editor: Dirk Balfanz, w3cid 47648, Google, balfanz@google.com
Former Editor: Vijay Bharadwaj, w3cid 55440, Microsoft, vijay.bharadwaj@microsoft.com
Former Editor: Arnar Birgisson, w3cid 87332, Google, arnarb@google.com
Former Editor: Alexei Czeskis, w3cid 87258, Google, aczeskis@google.com
Former Editor: Jeff Hodges, w3cid 43843, formerly Google
Former Editor: J.C. Jones, w3cid 87240, formerly Mozilla
Former Editor: Hubert Le Van Gong, w3cid 84817, PayPal, hlevangong@paypal.com
Former Editor: Angelo Liao, w3cid 94342, Microsoft, huliao@microsoft.com
Former Editor: Rolf Lindemann, w3cid 84447, Nok Nok Labs, rolf@noknok.com
!Contributors: <a href="mailto:WebAuthn@ve7jtb.com">John Bradley</a> (Yubico)
!Contributors: <a href="mailto:cbrand@google.com">Christiaan Brand</a> (Google)
!Contributors: <a href="mailto:agl@google.com">Adam Langley</a> (Google)
!Contributors: <a href="mailto:mandyam@qti.qualcomm.com">Giridhar Mandyam</a> (Qualcomm)
!Contributors: <a href="mailto:pascoe@apple.com">Pascoe</a> (Apple)
!Contributors: <a href="mailto:nsatragno@google.com">Nina Satragno</a> (Google)
!Contributors: <a href="mailto:kieun.shin@sk.com">Ki-Eun Shin</a> (SK Telecom)
!Contributors: <a href="mailto:nick.steele@agilebits.com">Nick Steele</a> (1Password)
!Contributors: <a href="mailto:jiewen_tan@apple.com">Jiewen Tan</a> (Apple)
!Contributors: <a href="mailto:sweeden@au1.ibm.com">Shane Weeden</a> (IBM)
!Contributors: <a href="mailto:mkwst@google.com">Mike West</a> (Google)
!Contributors: <a href="mailto:jyasskin@google.com">Jeffrey Yasskin</a> (Google)
!Contributors: <a href="mailto:aaberg@bitwarden.com">Anders Åberg</a> (Bitwarden)
group: webauthn
Issue Tracking: GitHub https://github.com/w3c/webauthn/issues
!Tests: <a href=https://github.com/web-platform-tests/wpt/tree/master/webauthn>web-platform-tests webauthn/</a> (<a href=https://github.com/web-platform-tests/wpt/labels/webauthn>ongoing work</a>)
Text Macro: FALSE <code>false</code>
Text Macro: PII personally identifying information
Text Macro: RP Relying Party
Text Macro: RPS Relying Parties
Text Macro: INFORMATIVE <em>This section is not normative.</em>
Text Macro: TRUE <code>true</code>
Text Macro: WAA WebAuthn Authenticator
Text Macro: WAAS WebAuthn Authenticator
Text Macro: WAC WebAuthn Client
Text Macro: WACS WebAuthn Clients
Text Macro: WRP WebAuthn Relying Party
Text Macro: WRPS WebAuthn Relying Parties
Text Macro: CREATE-METHOD-ARGS (origin, options, sameOriginWithAncestors)
Text Macro: CREATE-METHOD [[Create]][CREATE-METHOD-ARGS]
Text Macro: CREATE-METHOD-DEF \[[Create]][CREATE-METHOD-ARGS]
Text Macro: DISCOVER-METHOD-ARGS (origin, options, sameOriginWithAncestors)
Text Macro: DISCOVER-METHOD [[DiscoverFromExternalSource]][DISCOVER-METHOD-ARGS]
Text Macro: DISCOVER-METHOD-DEF \[[DiscoverFromExternalSource]][DISCOVER-METHOD-ARGS]
Ignored Vars: op, alg, type, algorithm
Abstract: This specification defines an API enabling the creation and use of strong, attested, [=scoped=], public key-based
 credentials by [=web applications=], for the purpose of strongly authenticating users. Conceptually, one or more [=public key
 credentials=], each [=scoped=] to a given [=WebAuthn Relying Party=], are created by and [=bound credential|bound=] to
 [=authenticators=] as requested by the web application. The user agent mediates access to [=authenticators=] and their [=public
 key credentials=] in order to preserve user
 privacy. [=Authenticators=] are responsible for ensuring that no operation is performed without [=user consent=].
 [=Authenticators=] provide cryptographic proof of their properties to [=Relying Parties=] via [=attestation=]. This
 specification also describes the functional model for WebAuthn conformant [=authenticators=], including their signature and
 [=attestation=] functionality.
Boilerplate: omit conformance, omit feedback-header, omit abstract-header
Markup Shorthands: css off, markdown on, macros-in-autolinks yes
Implementation Report: https://www.w3.org/2020/12/webauthn-report.html
</pre>

<style type="text/css">
body {
    counter-reset: table;
}
/* For some reason, doing the counter-increment on the figcaption like Bikeshed does with figures does not seem to work here. */
figure.table {
    counter-increment: table;
}
figure.table figcaption {
    counter-increment: none;
}
figure.table figcaption:not(.no-marker)::before {
    content: "Table " counter(table) " ";
}
figure.table .overlarge {
    max-width: 50em;
}

.figure-num-following::before {
    counter-increment: figure;
    content: counter(figure)
}

.figure-num-following::after {
    counter-increment: figure -1;
    content: ""
}

.figure-num-previous::before {
    content: counter(figure);
}

.table-ref-previous::before {
    content: counter(table);
}

.table-ref-following::before {
    counter-increment: table;
    content: counter(table);
}

.table-ref-following::after {
    counter-increment: table -1;
    content: "";
}
</style>

<!-- TODO: Clean out these anchor lists once they appear in Shepherd -->
<pre class="anchors">

spec: ECMAScript; urlPrefix: https://tc39.github.io/ecma262/#
    type: dfn
        text: %ArrayBuffer%; url: sec-arraybuffer-constructor
        url: sec-object-internal-methods-and-internal-slots
            text: internal method
            text: internal slot
        text: own property; url: sec-own-property

spec: RFC9052; urlPrefix: https://tools.ietf.org/html/rfc9052
    type: dfn; for: RFC9052
        text: COSE key; url: name-key-objects
        text: kty; url: name-cose-key-common-parameters
        text: section 7; url: section-7

spec: RFC9053; urlPrefix: https://tools.ietf.org/html/rfc9053
    type: dfn; for: RFC9053
        text: crv; url: name-double-coordinate-curves
        text: section 2.1; url: section-2.1
        text: section 2; url: section-2
        text: section 7.1; url: section-7.1

spec: RFC8230; urlPrefix: https://tools.ietf.org/html/rfc8230
    type: dfn; for: RFC8230
        text: Section 4; url: section-4
        text: Section 2; url: section-2

spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/
    type: dfn
        urlPrefix: browsers.html
            text: browsing context; url: browsing-context
        urlPrefix: origin.html
            text: origin; url: concept-origin
            text: document.domain; url:dom-document-domain
        urlPrefix: form-control-infrastructure.html
            text: autofill detail token; url: autofill-detail-tokens
            text: non-autofill credential type; url: non-autofill-credential-type

spec: url; urlPrefix: https://url.spec.whatwg.org
    type: dfn
        text: scheme; url: concept-url-scheme
        text: port; url: concept-url-port


spec: TokenBinding; urlPrefix: https://tools.ietf.org/html/rfc8471#
    type: dfn
        text: Token Binding; url: section-1
        text: Token Binding ID; url: section-3.2

spec: credential-management-1; urlPrefix: https://w3c.github.io/webappsec-credential-management/
    type: dfn
        text: same-origin with its ancestors; url: same-origin-with-its-ancestors

spec: FIDO-CTAP; urlPrefix: https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html
    type: dfn
        text: §6. Authenticator API; url: authenticator-api
        text: large, per-credential blobs; url: authenticatorLargeBlobs

spec: FIDO-APPID; urlPrefix: https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-appid-and-facets-v2.0-id-20180227.html
    type: dfn
        text: determining the FacetID of a calling application; url: determining-the-facetid-of-a-calling-application
        text: determining if a caller's FacetID is authorized for an AppID; url: determining-if-a-caller-s-facetid-is-authorized-for-an-appid

spec: FIDO-U2F-Message-Formats; urlPrefix: https://fidoalliance.org/specs/fido-u2f-v1.1-id-20160915/fido-u2f-raw-message-formats-v1.1-id-20160915.html
    type: dfn; for: FIDO-U2F-Message-Formats
        text: application parameter; url: authentication-request-message---u2f_authenticate
        text: Section 4.3; url: registration-response-message-success
        text: Section 5.4; url: authentication-response-message-success

spec: FIDO-Registry; urlPrefix: https://fidoalliance.org/specs/common-specs/fido-registry-v2.1-ps-20191217.html
    type: dfn; for: FIDO-Registry
        text: Section 3.6.2 Public Key Representation Formats; url: public-key-representation-formats

spec: RFC4949; urlPrefix: https://tools.ietf.org/html/rfc4949
    type: dfn
        text: man-in-the-middle attack; url: page-186
        text: salt; url: page-258
        text: salted; url: page-258

spec: SP800-800-63r3; urlPrefix: https://pages.nist.gov/800-63-3/sp800-63-3.html
    type: dfn
        text: authentication factor; url: af
        text: multi-factor; url: af
        text: second-factor; url: af
        text: single-factor; url: sf
        text: something you know; url: af
        text: something you have; url: af
        text: something you are; url: af

spec: webdriver; urlPrefix: https://w3c.github.io/webdriver/
    type: dfn
        text: Object; url: dfn-object
        text: WebDriver error; url: dfn-error
        text: WebDriver error code; url: dfn-error-code
        text: endpoint node; url: dfn-endpoint-node
        text: extension capability; url: dfn-extension-capability
        text: getting a property; url: dfn-getting-properties
        text: set a property; url: dfn-set-a-property
        text: matching capabilities; url: dfn-matching-capabilities
        text: unsupported operation; url: dfn-unsupported-operation
        text: validating capabilities; url: dfn-validate-capabilities

spec: RFC5280; urlPrefix: https://tools.ietf.org/html/rfc5280
    type: dfn
        text: SubjectPublicKeyInfo; url: section-4.1.2.7

spec: RFC8610; urlPrefix: https://tools.ietf.org/html/rfc8610
    type: dfn
        text: group sockets; url: section-3.9

</pre> <!-- class=anchors -->

<!-- L128 spec:webappsec-credential-management-1; type:dictionary; for:/; text:CredentialRequestOptions -->

<pre class="link-defaults">
spec:credential-management; type:dfn; text:credentials
spec:dom; type:dfn; for:/; text:document
spec:html; type:dfn; text:allowed to use
spec:html; type:dfn; for:environment settings object; text:global object
spec:html; type:dfn; for:/; text:same site
spec:infra; type:dfn; for:/; text:set
spec:infra; type:dfn; text:list
spec:url; type:dfn; text:domain
spec:url; type:dfn; for:url; text:host
spec:url; type:dfn; text:valid domain;
spec:webidl; type:dfn; text:DOMString
spec:webidl; type:interface; text:Promise
</pre>


# Introduction # {#sctn-intro}

[INFORMATIVE]

This specification defines an API enabling the creation and use of strong, attested, [=scoped=], public key-based
credentials by [=web applications=], for the purpose of strongly authenticating users. A [=public key credential=] is
created and stored by a <em>[=[WAA]=]</em> at the behest of a <em>[=[WRP]=]</em>, subject to <em>[=user
consent=]</em>. Subsequently, the [=public key credential=] can only be accessed by [=origins=] belonging to that [=[RP]=].
This scoping is enforced jointly by <em>[=conforming User Agents=]</em> and <em>[=authenticators=]</em>.
Additionally, privacy across [=[RPS]=] is maintained; [=[RPS]=] are not able to detect any properties, or even
the existence, of credentials [=scoped=] to other [=[RPS]=].

[=[RPS]=] employ the [=Web Authentication API=] during two distinct, but related, [=ceremonies=] involving a user. The first
is [=Registration=], where a [=public key credential=] is created on an [=authenticator=], and [=scoped=] to a [=[RP]=]
with the present user's account (the account might already exist or might be created at this time). The second is
[=Authentication=], where the [=[RP]=] is presented with an <em>[=Authentication Assertion=]</em> proving the presence
and [=user consent|consent=] of the user who registered the [=public key credential=]. Functionally, the [=Web Authentication
API=] comprises a {{PublicKeyCredential}} which extends the Credential Management API [[!CREDENTIAL-MANAGEMENT-1]], and
infrastructure which allows those credentials to be used with {{CredentialsContainer/create()|navigator.credentials.create()}} and
{{CredentialsContainer/get()|navigator.credentials.get()}}. The former is used during [=Registration=], and the
latter during [=Authentication=].

Broadly, compliant [=authenticators=] protect [=public key credentials=], and interact with user agents to implement the
[=Web Authentication API=].
Implementing compliant authenticators is possible in software executing
(a) on a general-purpose computing device,
(b) on an on-device Secure Execution Environment, Trusted Platform Module (TPM), or a Secure Element (SE), or
(c) off device.
Authenticators being implemented on device are called [=platform authenticators=].
Authenticators being implemented off device ([=roaming authenticators=]) can be accessed over a transport such
as Universal Serial Bus (USB), Bluetooth Low Energy (BLE), or Near Field Communications (NFC).

## Specification Roadmap ## {#sctn-spec-roadmap}

While many W3C specifications are directed primarily to user agent developers and also to web application developers
(i.e., "Web authors"), the nature of Web Authentication requires that this specification be correctly used by multiple audiences,
as described below.

**All audiences** ought to begin with [[#sctn-use-cases]], [[#sctn-sample-scenarios]], and [[#sctn-terminology]], and should also
refer to [[WebAuthnAPIGuide]] for an overall tutorial.
Beyond that, the intended audiences for this document are the following main groups:

- [=[RP]=] web application developers, especially those responsible for [=[RP]=] [=web application=] login flows, account recovery flows,
    user account database content, etc.
- Web framework developers

    - The above two audiences should in particular refer to [[#sctn-rp-operations]].
        The introduction to [[#sctn-api]] may be helpful, though readers should realize that the [[#sctn-api]] section is targeted specifically
        at user agent developers, not web application developers.
        Additionally, if they intend to verify [=authenticator=] [=attestations=], then
        [[#sctn-attestation]] and [[#sctn-defined-attestation-formats]] will also be relevant.
        [[#sctn-extensions]], and [[#sctn-defined-extensions]] will be of interest if they wish to make use of extensions.
        Finally, they should read [[#sctn-security-considerations-rp]] and [[#sctn-privacy-considerations-rp]]
        and consider which challenges apply to their application and users.

- User agent developers
- OS platform developers, responsible for OS platform API design and implementation in regards to platform-specific
    [=authenticator=] APIs, platform [=WebAuthn Client=] instantiation, etc.

    - The above two audiences should read [[#sctn-api]] very carefully, along with [[#sctn-extensions]] if they intend to support extensions.
        They should also carefully read
        <!-- no sec cons for clients enumerated at this time
        [[#sctn-security-considerations-client]] and
        -->
        [[#sctn-privacy-considerations-client]].

- [=Authenticator=] developers. These readers will want to pay particular attention to [[#sctn-authenticator-model]],
    [[#sctn-defined-attestation-formats]], [[#sctn-extensions]], and [[#sctn-defined-extensions]].
    They should also carefully read [[#sctn-security-considerations-authenticator]] and [[#sctn-privacy-considerations-authenticator]].

<div class="note">
    <span class="marker">Note:</span>
    Along with the [[#sctn-api|Web Authentication API]] itself, this specification defines a
    request-response <em>cryptographic protocol</em>&mdash;the
    <dfn export>WebAuthn/FIDO2 protocol</dfn>&mdash;between
    a [=[WRP]=] server and an [=authenticator=], where the [=[RP]=]'s request consists of a
    [[#sctn-cryptographic-challenges|challenge]] and other
    input data supplied by the [=[RP]=] and sent to the [=authenticator=].
    The request is conveyed via the
    combination of HTTPS, the [=[RP]=] [=web application=], the [[#sctn-api|WebAuthn API]], and the platform-specific communications channel
    between the user agent and the [=authenticator=].
    The [=authenticator=] replies with a digitally signed [=authenticator data=] message and other output data, which is conveyed back to the
    [=[RP]=] server via the same path in reverse. Protocol details vary according to whether an [=authentication=] or
    [=registration=] operation is invoked by the [=[RP]=].
    See also [Figure 1](#fig-registration) and [Figure 2](#fig-authentication).

    <strong>It is important for Web Authentication deployments' end-to-end security</strong> that the role of each
    component&mdash;the [=[RP]=] server, the [=client=], and the [=authenticator=]&mdash;
    as well as [[#sctn-security-considerations]] and [[#sctn-privacy-considerations]], are understood <em>by all audiences</em>.
</div>

## Use Cases ## {#sctn-use-cases}

The below use case scenarios illustrate use of two very different types of [=authenticators=] and credentials across two common deployment types, 
as well as outline further scenarios. Additional scenarios, including sample code, are given later in [[#sctn-sample-scenarios]]. 
These examples are for illustrative purposes only, and feature availability may differ between client and authenticator implementations.

### Consumer with Multi-Device Credentials ### {#sctn-usecase-consumer-mdc}

This use case illustrates how a consumer-centric [=[RP]=] can leverage the authenticator built-in to a user's devices 
to provide phishing-resistant sign in using [=multi-device credentials=] (commonly referred to as synced [=passkeys=]). 

#### Registration #### {#sctn-usecase-consumer-mdc-reg}

- On a phone:
    * User navigates to example.com in a browser and signs in to an existing account using whatever method they have been using
        (possibly a legacy method such as a password), or creates a new account.
    * The phone prompts, "Do you want to create a passkey for example.com?"
    * User agrees.
    * The phone prompts the user for a previously configured [=authorization gesture=] (PIN, biometric, etc.); the user
        provides this.
    * Website shows message, "Registration complete."

#### Authentication #### {#sctn-usecase-consumer-mdc-auth}

- On a laptop or desktop:
    * User navigates to example.com in a browser and initiates signing in.
    * If the [=multi-device credential=] (commonly referred to as a synced [=passkey=]) is available on the device:
        * The browser or operating system prompts the user for a previously configured [=authorization gesture=] (PIN, biometric, etc.); 
            the user provides this.
        * Web page shows that the selected user is signed in, and navigates to the signed-in page.
    * If the synced [=passkey=] is not available on the device:
        * The browser or operating system prompts the user for an external authenticator,
            such as a phone or security key.
        * The user selects a previously linked phone.

- Next, on their phone:
    * User sees a discrete prompt or notification, "Sign in to example.com."
    * User selects this prompt / notification.
    * User is shown a list of their example.com identities, e.g., "Sign in as Mohamed / Sign in as 张三".
    * User picks an identity, is prompted for an [=authorization gesture=] (PIN, biometric, etc.) and provides this.

- Now, back on the laptop:
    * Web page shows that the selected user is signed in, and navigates to the signed-in page.


### Workforce with Single-Device Credentials ### {#sctn-usecase-workforce-sdc}

This use case illustrates how a workforce-centric [=[RP]=] can leverage a combination of a [=roaming authenticator=] (e.g., a USB security
key) and a [=platform authenticator=] (e.g., a built-in fingerprint sensor) such that the user has:

  - a "primary" [=roaming authenticator=] that they use to authenticate on new-to-them [=client devices=] (e.g., laptops,
    desktops) or on such [=client devices=] that lack a [=platform authenticator=], and
  - a low-friction means to strongly re-authenticate on [=client devices=] having [=platform authenticators=], or
  - a means to strongly re-authenticate on [=client devices=] having [=passkey platform authenticators=] which do not support [=single-device credentials=]
    (commonly referred to as device-bound [=passkeys=]).

#### Registration #### {#sctn-usecase-workforce-sdc-reg}

In this example, the user's employer mails a security key which is preconfigured with a device-bound [=passkey=].

A temporary PIN was sent to the user out of band (e.g., via an RCS message).

#### Authentication #### {#sctn-usecase-workforce-sdc-auth}

- On a laptop or desktop:
    * User navigates to corp.example.com in a browser and initiates signing in.
    * The browser or operating system prompts the user for their security key.
    * The user connects their USB security key.
    * The USB security key blinks to indicate the user should press the button on it; the user does.
    * The browser or operating system asks the user to enter their PIN.
    * The user enters the temporary PIN they were provided and continues.
    * The browser or operating system informs the user that they must change their PIN and prompts for a new one.
    * The user enters their new PIN and continues.
    * The browser or operating system restarts the authentication flow and asks the user to enter their PIN.
    * The user enters their new PIN and taps the security key.
    * Web page shows that the selected user is signed in, and navigates to the signed-in page.


### Other Use Cases and Configurations ### {#sctn-other-configurations}

A variety of additional use cases and configurations are also possible, including (but not limited to):

- A user navigates to example.com on their laptop, is guided through a flow to create and register a credential on their phone.

- A user obtains a discrete, [=roaming authenticator=], such as a security key with USB and/or NFC connectivity options, loads
    example.com in their browser on a laptop or phone, and is guided through a flow to create and register a credential on the
    security key.

- A [=[RP]=] prompts the user for their [=authorization gesture=] in order to authorize a single transaction, such as a payment
    or other financial transaction.

## Sample API Usage Scenarios ## {#sctn-sample-scenarios}

[INFORMATIVE]

In this section, we walk through some events in the lifecycle of a [=public key credential=], along with the corresponding
sample code for using this API. Note that this is an example flow and does not limit the scope of how the API can be used.

As was the case in earlier sections, this flow focuses on a use case involving a [=passkey roaming authenticator=]
with its own display. One example of such an authenticator would be a smart phone. Other authenticator types are also supported
by this API, subject to implementation by the [=client platform=]. For instance, this flow also works without modification for the case of
an authenticator that is embedded in the [=client device=]. The flow also works for the case of an authenticator without
its own display (similar to a smart card) subject to specific implementation considerations. Specifically, the [=client platform=]
needs to display any prompts that would otherwise be shown by the authenticator, and the authenticator needs to allow the [=client
platform=] to enumerate all the authenticator's credentials so that the client can have information to show appropriate prompts.


### Registration ### {#sctn-sample-registration}

This is the first-time flow, in which a new credential is created and registered with the server.
In this flow, the [=[WRP]=] does not have a preference for [=platform authenticator=] or [=roaming authenticators=].

1. The user visits example.com, which serves up a script. At this point, the user may already be logged in using a legacy
    username and password, or additional authenticator, or other means acceptable to the [=[RP]=].
    Or the user may be in the process of creating a new account.

1. The [=[RP]=] script runs the code snippet below.

1. The [=client platform=] searches for and locates the authenticator.

1. The [=client=] connects to the authenticator, performing any pairing actions if necessary.

1. The authenticator shows appropriate UI for the user to provide a biometric or other [=authorization gesture=].

1. The authenticator returns a response to the [=client=], which in turn returns a response to the [=[RP]=] script. If
    the user declined to select an authenticator or provide authorization, an appropriate error is returned.

1. If a new credential was created,
    - The [=[RP]=] script sends the newly generated [=credential public key=] to the server, along with additional information
        such as attestation regarding the provenance and characteristics of the authenticator.
    - The server stores the [=credential public key=] in its database and associates it with the user as well as with the
        characteristics of authentication indicated by attestation, also storing a friendly name for later use.
    - The script may store data such as the [=credential ID=] in local storage, to improve future UX by narrowing the choice of
        credential for the user.

The sample code for generating and registering a new key follows:

<xmp class="example" highlight="js">
    if (!window.PublicKeyCredential) { /* Client not capable. Handle error. */ }

    var publicKey = {
      // The challenge is produced by the server; see the Security Considerations
      challenge: new Uint8Array([21,31,105 /* 29 more random bytes generated by the server */]),

      // Relying Party:
      rp: {
        name: "ACME Corporation"
      },

      // User:
      user: {
        id: Uint8Array.from(window.atob("MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII="), c=>c.charCodeAt(0)),
        name: "alex.mueller@example.com",
        displayName: "Alex Müller",
      },

      // This Relying Party will accept either an EdDSA, ES256 or RS256 credential, but
      // prefers an EdDSA credential.
      pubKeyCredParams: [
        {
          type: "public-key",
          alg: -8 // "EdDSA" as registered in the IANA COSE Algorithms registry
        },
        {
          type: "public-key",
          alg: -7 // "ES256" as registered in the IANA COSE Algorithms registry
        },
        {
          type: "public-key",
          alg: -257 // Value registered by this specification for "RS256"
        }
      ],

      authenticatorSelection: {
        // Try to use UV if possible. This is also the default.
        userVerification: "preferred"
      },

      timeout: 300000,  // 5 minutes
      excludeCredentials: [
        // Don't re-register any authenticator that has one of these credentials
        {"id": Uint8Array.from(window.atob("ufJWp8YGlibm1Kd9XQBWN1WAw2jy5In2Xhon9HAqcXE="), c=>c.charCodeAt(0)), "type": "public-key"},
        {"id": Uint8Array.from(window.atob("E/e1dhZc++mIsz4f9hb6NifAzJpF1V4mEtRlIPBiWdY="), c=>c.charCodeAt(0)), "type": "public-key"}
      ],

      // Make excludeCredentials check backwards compatible with credentials registered with U2F
      extensions: {"appidExclude": "https://acme.example.com"}
    };

    // Note: The following call will cause the authenticator to display UI.
    navigator.credentials.create({ publicKey })
      .then(function (newCredentialInfo) {
        // Send new credential info to server for verification and registration.
      }).catch(function (err) {
        // No acceptable authenticator or user refused consent. Handle appropriately.
      });
</xmp>

### Registration Specifically with User-Verifying Platform Authenticator ### {#sctn-sample-registration-with-platform-authenticator}

This is an example flow for when the [=[WRP]=] is specifically interested in creating a [=public key credential=] with
a [=user-verifying platform authenticator=].

1. The user visits example.com and clicks on the login button, which redirects the user to login.example.com.

1. The user enters a username and password to log in. After successful login, the user is redirected back to example.com.

1. The [=[RP]=] script runs the code snippet below.

    1. The user agent checks if a [=user-verifying platform authenticator=] is available. If not, terminate this flow.

    1. The [=[RP]=] asks the user if they want to create a credential with it. If not, terminate this flow.

    1. The user agent and/or operating system shows appropriate UI and guides the user in creating a credential
        using one of the available platform authenticators.

    1. Upon successful credential creation, the [=[RP]=] script conveys the new credential to the server.

<xmp class="example" highlight="js">
    if (!window.PublicKeyCredential) { /* Client not capable of the API. Handle error. */ }

    PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
        .then(function (uvpaAvailable) {
            // If there is a user-verifying platform authenticator
            if (uvpaAvailable) {
                // Render some RP-specific UI and get a Promise for a Boolean value
                return askIfUserWantsToCreateCredential();
            }
        }).then(function (userSaidYes) {
            // If there is a user-verifying platform authenticator
            // AND the user wants to create a credential
            if (userSaidYes) {
                var publicKeyOptions = { /* Public key credential creation options. */};
                return navigator.credentials.create({ "publicKey": publicKeyOptions });
            }
        }).then(function (newCredentialInfo) {
            if (newCredentialInfo) {
                // Send new credential info to server for verification and registration.
            }
        }).catch(function (err) {
            // Something went wrong. Handle appropriately.
        });
</xmp>

### Authentication ### {#sctn-sample-authentication}

This is the flow when a user with an already registered credential visits a website and wants to authenticate using the
credential.

1. The user visits example.com, which serves up a script.

1. The script asks the [=client=] for an Authentication Assertion, providing as much information as possible to narrow
    the choice of acceptable credentials for the user. This can be obtained from the data that was stored locally after
    registration, or by other means such as prompting the user for a username.

1. The [=[RP]=] script runs one of the code snippets below.

1. The [=client platform=] searches for and locates the authenticator.

1. The [=client=] connects to the authenticator, performing any pairing actions if necessary.

1. The authenticator presents the user with a notification that their attention is needed. On opening the
    notification, the user is shown a friendly selection menu of acceptable credentials using the account information provided
    when creating the credentials, along with some information on the [=origin=] that is requesting these keys.

1. The authenticator obtains a biometric or other [=authorization gesture=] from the user.

1. The authenticator returns a response to the [=client=], which in turn returns a response to the [=[RP]=] script.
    If the user declined to select a credential or provide an authorization, an appropriate error is returned.

1. If an assertion was successfully generated and returned,
    - The script sends the assertion to the server.
    - The server examines the assertion, extracts the [=credential ID=], looks up the registered
        credential public key in its database, and verifies the [=assertion signature=].
        If valid, it looks up the identity associated with the assertion's [=credential ID=]; that
        identity is now authenticated. If the [=credential ID=] is not recognized by the server (e.g.,
        it has been deregistered due to inactivity) then the authentication has failed; each [=[RP]=]
        will handle this in its own way.
    - The server now does whatever it would otherwise do upon successful authentication -- return a success page, set
        authentication cookies, etc.

If the [=[RP]=] script does not have any hints available (e.g., from locally stored data) to help it narrow the list of
credentials, then the sample code for performing such an authentication might look like this:

<xmp class="example" highlight="js">
    if (!window.PublicKeyCredential) { /* Client not capable. Handle error. */ }

    // credentialId is generated by the authenticator and is an opaque random byte array
    var credentialId = new Uint8Array([183, 148, 245 /* more random bytes previously generated by the authenticator */]);
    var options = {
      // The challenge is produced by the server; see the Security Considerations
      challenge: new Uint8Array([4,101,15 /* 29 more random bytes generated by the server */]),
      timeout: 300000,  // 5 minutes
      allowCredentials: [{ type: "public-key", id: credentialId }]
    };

    navigator.credentials.get({ "publicKey": options })
        .then(function (assertion) {
        // Send assertion to server for verification
    }).catch(function (err) {
        // No acceptable credential or user refused consent. Handle appropriately.
    });
</xmp>

On the other hand, if the [=[RP]=] script has some hints to help it narrow the list of credentials, then the sample code for
performing such an authentication might look like the following. Note that this sample also demonstrates how to use the [=credProps|Credential Properties Extension=].

<xmp class="example" highlight="js">
    if (!window.PublicKeyCredential) { /* Client not capable. Handle error. */ }

    var encoder = new TextEncoder();
    var acceptableCredential1 = {
        type: "public-key",
        id: encoder.encode("BA44712732CE")
    };
    var acceptableCredential2 = {
        type: "public-key",
        id: encoder.encode("BG35122345NF")
    };

    var options = {
      // The challenge is produced by the server; see the Security Considerations
      challenge: new Uint8Array([8,18,33 /* 29 more random bytes generated by the server */]),
      timeout: 300000,  // 5 minutes
      allowCredentials: [acceptableCredential1, acceptableCredential2],
      extensions: { 'credProps': true }
    };

    navigator.credentials.get({ "publicKey": options })
        .then(function (assertion) {
        // Send assertion to server for verification
    }).catch(function (err) {
        // No acceptable credential or user refused consent. Handle appropriately.
    });
</xmp>

### Aborting Authentication Operations ### {#sctn-sample-aborting}

The below example shows how a developer may use the AbortSignal parameter to abort a
credential registration operation. A similar procedure applies to an authentication operation.

<xmp class="example" highlight="js">
    const authAbortController = new AbortController();
    const authAbortSignal = authAbortController.signal;

    authAbortSignal.onabort = function () {
        // Once the page knows the abort started, inform user it is attempting to abort.
    }

    var options = {
        // A list of options.
    }

    navigator.credentials.create({
        publicKey: options,
        signal: authAbortSignal})
        .then(function (attestation) {
            // Register the user.
        }).catch(function (error) {
            if (error.name === "AbortError") {
                // Inform user the credential hasn't been created.
                // Let the server know a key hasn't been created.
            }
        });

    // Assume widget shows up whenever authentication occurs.
    if (widget == "disappear") {
        authAbortController.abort();
    }
</xmp>


### Decommissioning ### {#sctn-sample-decommissioning}

The following are possible situations in which decommissioning a credential might be desired. Note that all of these are
handled on the server side and do not need support from the API specified here.

- Possibility #1 -- user reports the credential as lost.
    * User goes to server.example.net, authenticates and follows a link to report a lost/stolen [=authenticator=].
    * Server returns a page showing the list of registered credentials with friendly names as configured during registration.
    * User selects a credential and the server deletes it from its database.
    * In the future, the [=[RP]=] script does not specify this credential in any list of acceptable credentials, and assertions
        signed by this credential are rejected.

- Possibility #2 -- server deregisters the credential due to inactivity.
    * Server deletes credential from its database during maintenance activity.
    * In the future, the [=[RP]=] script does not specify this credential in any list of acceptable credentials, and assertions
        signed by this credential are rejected.

- Possibility #3 -- user deletes the credential from the [=authenticator=].
    * User employs a [=authenticator=]-specific method (e.g., device settings UI) to delete a credential from their [=authenticator=].
    * From this point on, this credential will not appear in any selection prompts, and no assertions can be generated with it.
    * Sometime later, the server deregisters this credential due to inactivity.


##  Platform-Specific Implementation Guidance ## {#sctn-platform-impl-guidance}

This specification defines how to use Web Authentication in the general case. When using Web
Authentication in connection with specific platform support (e.g. apps), it is recommended to see
platform-specific documentation and guides for additional guidance and limitations.



# Conformance # {#sctn-conformance}

This specification defines three conformance classes. Each of these classes is specified so that conforming members of the class
are secure against non-conforming or hostile members of the other classes.

## User Agents ## {#sctn-conforming-user-agents}

A User Agent MUST behave as described by [[#sctn-api]] in order to be considered conformant. [=Conforming User Agents=] MAY implement
algorithms given in this specification in any way desired, so long as the end result is indistinguishable from the result that
would be obtained by the specification's algorithms.

A conforming User Agent MUST also be a conforming implementation of the IDL fragments of this specification, as described in the
“Web IDL” specification. [[!WebIDL]]

### Enumerations as DOMString types ### {#sct-domstring-backwards-compatibility}

Enumeration types are not referenced by other parts of the Web IDL because that
would preclude other values from being used without updating this specification
and its implementations. It is important for backwards compatibility that
[=client platforms=] and [=[RPS]=] handle unknown values. Enumerations for this
specification exist here for documentation and as a registry. Where the
enumerations are represented elsewhere, they are typed as {{DOMString}}s, for
example in {{PublicKeyCredentialDescriptor/transports}}.

## Authenticators ## {#sctn-conforming-authenticators}

A [=[WAA]=] MUST provide the operations defined by [[#sctn-authenticator-model]], and those operations MUST behave as
described there. This is a set of functional and security requirements for an authenticator to be usable by a [=Conforming User
Agent=].

As described in [[#sctn-use-cases]], an authenticator may be implemented in the operating system underlying the User Agent, or in
external hardware, or a combination of both.

### Backwards Compatibility with FIDO U2F ### {#sctn-conforming-authenticators-u2f}

[=Authenticators=] that only support the [[#sctn-fido-u2f-attestation]] have no mechanism to store a
[=user handle=], so the returned {{AuthenticatorAssertionResponse/userHandle}} will always be null.

## [WRPS] ## {#sctn-conforming-relying-parties}

A [=[WRP]=] MUST behave as described in [[#sctn-rp-operations]] to obtain all the security benefits offered by this specification. See
[[#sctn-rp-benefits]] for further discussion of this.


## All Conformance Classes ## {#sctn-conforming-all-classes}

All [=CBOR=] encoding performed by the members of the above conformance classes MUST be done using the
[=CTAP2 canonical CBOR encoding form=].
All decoders of the above conformance classes SHOULD reject CBOR that is not validly encoded
in the [=CTAP2 canonical CBOR encoding form=] and SHOULD reject messages with duplicate map keys.


# Dependencies # {#sctn-dependencies}

This specification relies on several other underlying specifications, listed
below and in [[#index-defined-elsewhere]].

: Base64url encoding
:: The term <dfn>Base64url Encoding</dfn> refers to the base64 encoding using the URL- and filename-safe character set defined
    in Section 5 of [[!RFC4648]], with all trailing '=' characters omitted (as permitted by Section 3.2) and without the
    inclusion of any line breaks, whitespace, or other additional characters.

: CBOR
:: A number of structures in this specification, including attestation statements and extensions, are encoded using the
    [=CTAP2 canonical CBOR encoding form=] of the Compact Binary Object Representation (<dfn>CBOR</dfn>) [[!RFC8949]],
    as defined in [[!FIDO-CTAP]].

: CDDL
:: This specification describes the syntax of all [=CBOR=]-encoded data using the CBOR Data Definition Language (<dfn>CDDL</dfn>) [[!RFC8610]].

: COSE
:: CBOR Object Signing and Encryption (COSE) [[!RFC9052]] [[!RFC9053]].
    The IANA COSE Algorithms registry [[!IANA-COSE-ALGS-REG]] originally established by [[!RFC8152 obsolete]] and updated by these specifications is also used.

:  Credential Management
:: The API described in this document is an extension of the {{Credential}} concept defined in [[!CREDENTIAL-MANAGEMENT-1]].

: DOM
:: {{DOMException}} and the DOMException values used in this specification are defined in [[!DOM4]].

: ECMAScript
:: [=%ArrayBuffer%=] is defined in [[!ECMAScript]].

: URL
:: The concepts of [=domain=], [=host=], [=port=], [=scheme=], [=valid domain=] and [=valid domain string=] are defined in [[!URL]].

: Web IDL
:: Many of the interface definitions and all of the IDL in this specification depend on [[!WebIDL]]. This updated version of
    the Web IDL standard adds support for {{Promise}}s, which are now the preferred mechanism for asynchronous
    interaction in all new web APIs.

: FIDO AppID
:: The algorithms for [=determining the FacetID of a calling application=] and
    [=determining if a caller's FacetID is authorized for an AppID=] (used only in
    the [=AppID|AppID extension=]) are defined by [[!FIDO-APPID]].

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",
"NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in
BCP 14 [[!RFC2119]] [[!RFC8174]] when, and only when, they appear in all capitals, as shown here.


# Terminology # {#sctn-terminology}

: <dfn>Attestation</dfn>
:: Generally, <em>attestation</em> is a statement that serves to bear witness, confirm, or authenticate.
    In the WebAuthn context, [=attestation=] is employed to provide verifiable evidence as to the origin of an [=authenticator=]
    and the data it emits. This includes such things as [=credential IDs=], [=credential key pairs=], [=signature counters=], etc.

    An [=attestation statement=] is provided within an [=attestation object=] during a [=registration=] ceremony. See also [[#sctn-attestation]]
    and [Figure 6](#fig-attStructs). Whether or how the [=client=] conveys the [=attestation statement=] and [=authData/attestedCredentialData/aaguid=]
    portions of the [=attestation object=] to the [=[RP]=] is described by [=attestation conveyance=].

: <dfn>Attestation Certificate</dfn>
:: An X.509 Certificate for the <dfn>attestation key pair</dfn> used by an [=authenticator=] to attest to its manufacture
    and capabilities. At [=registration=] time, the [=authenticator=] uses the <dfn>attestation private key</dfn> to sign
    the [=[RP]=]-specific [=credential public key=] (and additional data) that it generates and returns via the
    [=authenticatorMakeCredential=] operation. [=[RPS]=] use the <dfn>attestation public key</dfn> conveyed in the [=attestation
    certificate=] to verify the [=attestation signature=]. Note that in the case of [=self attestation=], the
    [=authenticator=] has no distinct [=attestation key pair=] nor [=attestation certificate=], see [=self
    attestation=] for details.

: <dfn>Authentication</dfn>
: <dfn>Authentication Ceremony</dfn>
:: The [=ceremony=] where a user, and the user's [=client platform=] (containing or connected to at least one [=authenticator=]) work in
    concert to cryptographically prove to a [=[RP]=] that the user controls the [=credential private key=] of a
    previously-registered [=public key credential=] (see [=Registration=]). Note that this includes a [=test of user presence=] or
    [=user verification=].

    The WebAuthn [=authentication ceremony=] is defined in [[#sctn-verifying-assertion]],
    and is initiated by the [=[RP]=] invoking a <code>{{CredentialsContainer/get()|navigator.credentials.get()}}</code> operation
    with a {{CredentialRequestOptions/publicKey}} argument.
    See [[#sctn-api]] for an introductory overview and [[#sctn-sample-authentication]] for implementation examples.

: <dfn>Authentication Assertion</dfn>
: <dfn>Assertion</dfn>
:: The cryptographically signed {{AuthenticatorAssertionResponse}} object returned by an [=authenticator=] as the result of an
    [=authenticatorGetAssertion=] operation.

    This corresponds to the [[!CREDENTIAL-MANAGEMENT-1]] specification's single-use <a
    spec="credential-management">credentials</a>.

: <dfn>Authenticator</dfn>
: <dfn>[WAA]</dfn>
:: A cryptographic entity, existing in hardware or software, that can [=registration|register=] a user with a given [=[RP]=]
    and later [=Authentication Assertion|assert possession=] of the registered [=public key credential=], and optionally
    [=user verification|verify the user=] to the [=[RP]=]. [=Authenticators=] can report information
    regarding their [=authenticator types|type=] and security characteristics via [=attestation=] during [=registration=]
    and [=assertion=].

    A [=[WAA]=] could be a [=roaming authenticator=], a dedicated hardware subsystem integrated into the [=client device=],
    or a software component of the [=client=] or [=client device=]. A [=[WAA]=] is not necessarily confined to operating in
    a local context, and can generate or store a [=credential key pair=] in a server outside of [=client-side=] hardware.

    In general, an [=authenticator=] is assumed to have only one user.
    If multiple natural persons share access to an [=authenticator=],
    they are considered to represent the same user in the context of that [=authenticator=].
    If an [=authenticator=] implementation supports multiple users in separated compartments,
    then each compartment is considered a separate [=authenticator=]
    with a single user with no access to other users' [=credentials=].

: <dfn>Authorization Gesture</dfn>
:: An [=authorization gesture=] is a physical interaction performed by a user with an authenticator as part of a [=ceremony=],
    such as [=registration=] or [=authentication=]. By making such an [=authorization gesture=], a user [=user consent|provides
    consent=] for (i.e., <em>authorizes</em>) a [=ceremony=] to proceed. This MAY involve [=user verification=] if the
    employed [=authenticator=] is capable, or it MAY involve a simple [=test of user presence=].

: <dfn>Backed Up</dfn>
:: [=Public Key Credential Sources=] may be backed up in some fashion such that they may become present on an authenticator other
    than their [=generating authenticator=]. Backup can occur via mechanisms including but not limited to peer-to-peer sync,
    cloud sync, local network sync, and manual import/export. See also [[#sctn-credential-backup]].

: <dfn>Backup Eligibility</dfn>
: <dfn>Backup Eligible</dfn>
:: A [=Public Key Credential Source=]'s [=generating authenticator=] determines at creation time whether the [=public key credential source=]
    is allowed to be [=backed up=]. Backup eligibility is signaled in [=authenticator data=]'s [=flags=] along with the current [=backup state=].
    Backup eligibility is a [=credential property=] and is permanent for a given [=public key credential source=].
    A backup eligible [=public key credential source=] is referred to as a <dfn>multi-device credential</dfn> whereas one that is not
    backup eligible is referred to as a <dfn>single-device credential</dfn>. See also [[#sctn-credential-backup]].

: <dfn>Backup State</dfn>
:: The current backup state of a [=multi-device credential=] as determined by the current [=managing authenticator=]. Backup state is
    signaled in [=authenticator data=]'s [=flags=] and can change over time. See also [=backup eligibility=] and [[#sctn-credential-backup]].

: <dfn>Biometric Authenticator</dfn>
:: Any [=authenticator=] that implements [=biometric recognition=].

: <dfn>Biometric Recognition</dfn>
:: The automated recognition of individuals based on their biological and behavioral characteristics [[ISOBiometricVocabulary]].

: <dfn>Bound credential</dfn>
: "Authenticator [=contains=] a credential"
: "Credential [=created on=] an authenticator"
:: A [=public key credential source=] or [=public key credential=] is said to be [=bound credential|bound=] to its [=managing
    authenticator=]. This means that only the [=managing authenticator=] can generate [=assertions=] for the [=public key
    credential sources=] [=bound credential|bound=] to it.

    This may also be expressed as "the [=managing authenticator=] <dfn>contains</dfn> the [=bound credential=]",
    or "the [=bound credential=] was <dfn>created on</dfn> its [=managing authenticator=]".
    Note, however, that a [=server-side credential=] might not be physically stored in persistent memory inside the authenticator,
    hence "[=bound credential|bound to=]" is the primary term.
    See [[#sctn-credential-storage-modality]].

: <dfn>Ceremony</dfn>
:: The concept of a [=ceremony=] [[Ceremony]] is an extension of the concept of a network protocol, with human nodes alongside
    computer nodes and with communication links that include user interface(s), human-to-human communication, and transfers of
    physical objects that carry data. What is out-of-band to a protocol is in-band to a ceremony. In this specification,
    [=Registration=] and [=Authentication=] are ceremonies, and an [=authorization gesture=] is often a component of
    those [=ceremonies=].

: <dfn>Client</dfn>
: <dfn>[WAC]</dfn>
:: Also referred to herein as simply a [=client=]. See also [=Conforming User Agent=]. A [=[WAC]=] is an intermediary entity typically implemented in the user agent (in whole, or in part). Conceptually, it underlies the [=Web Authentication API=] and embodies the implementation of the {{PublicKeyCredential/[CREATE-METHOD]}} and {{PublicKeyCredential/[DISCOVER-METHOD]}} [=internal methods=]. It is responsible for both marshalling the inputs for the underlying [=authenticator operations=], and for returning the results of the latter operations to the [=Web Authentication API=]'s callers.

    The [=[WAC]=] runs on, and is distinct from, a [=[WAC] Device=].

: <dfn>Client Device</dfn>
: <dfn>[WAC] Device</dfn>
:: The hardware device on which the [=[WAC]=] runs, for example a smartphone, a laptop computer or a desktop computer, and the
    operating system running on that hardware.

    The distinctions between a [=[WAC] device=] and a [=client=] are:
    * a single [=client device=] MAY support running multiple [=clients=], i.e., browser implementations,
        which all have access to the same [=authenticators=] available on that [=client device=], and
    * [=platform authenticators=] are bound to a [=client device=] rather than a [=[WAC]=].

    A [=client device=] and a [=client=] together constitute a [=client platform=].

: <dfn>Client Platform</dfn>
:: A [=client device=] and a [=client=] together make up a [=client platform=]. A single hardware device MAY be part of multiple
    distinct [=client platforms=] at different times by running different operating systems and/or [=clients=].

: <dfn>Client-Side</dfn>
:: This refers in general to the combination of the user's [=client platform=], [=authenticators=], and everything gluing
    it all together.

: <dfn>Client-side discoverable Public Key Credential Source</dfn>
: <dfn>Client-side discoverable Credential</dfn>
: <dfn>Discoverable Credential</dfn>
: <dfn export>Passkey</dfn>
: \[DEPRECATED] <dfn>Resident Credential</dfn>
: \[DEPRECATED] <dfn>Resident Key</dfn>
:: Note: Historically, [=client-side discoverable credentials=] have  been known as [=resident credentials=] or [=resident keys=].
    Due to the phrases `ResidentKey` and `residentKey` being widely used in both the [=web authentication api|WebAuthn
    API=] and also in the [=Authenticator Model=] (e.g., in dictionary member names, algorithm variable names, and
    operation parameters) the usage of `resident` within their
    names has not been changed for backwards compatibility purposes. Also, the term [=resident key=] is
    defined here as equivalent to a [=client-side discoverable credential=].

    A [=Client-side discoverable Public Key Credential Source=], or [=Discoverable Credential=] for short,
    is a [=public key credential source=] that is <strong><em>discoverable</em></strong> and usable in [=authentication ceremonies=]
    where the [=[RP]=] does not provide any [=credential ID=]s,
    i.e., the [=[RP]=] invokes {{CredentialsContainer/get()|navigator.credentials.get()}}
    with an <strong><em>[=list/is empty|empty=]</em></strong> {{PublicKeyCredentialRequestOptions/allowCredentials}} argument. This means that the [=[RP]=] does not necessarily need to first identify the user.

    As a consequence, a [=discoverable credential capable=] [=authenticator=] can generate an [=assertion signature=]
    for a [=discoverable credential=] given only an [=RP ID=],
    which in turn necessitates that the [=public key credential source=]
    is stored in the [=authenticator=] or [=client platform=].
    This is in contrast to a [=Server-side Public Key Credential Source=],
    which requires that the [=authenticator=] is given both the [=RP ID=] and the [=credential ID=]
    but does not require [=client-side=] storage of the [=public key credential source=].

    See also: [=client-side credential storage modality=] and [=non-discoverable credential=].

    Note: [=Client-side discoverable credentials=] are also usable in [=authentication ceremonies=] where [=credential ID=]s are given,
    i.e., when calling {{CredentialsContainer/get()|navigator.credentials.get()}}
    with a non-[=list/is empty|empty=] {{PublicKeyCredentialRequestOptions/allowCredentials}} argument.

: <dfn>Conforming User Agent</dfn>
:: A user agent implementing, in cooperation with the underlying [=client device=], the [=Web Authentication API=] and algorithms
    given in this specification, and handling communication between [=authenticators=] and [=[RPS]=].

: <dfn>Credential ID</dfn>
:: A probabilistically-unique [=byte sequence=] identifying a [=public key credential source=] and its [=authentication assertions=]. At most 1023 bytes long.

    Credential IDs are generated by [=authenticators=] in two forms:
    1. At least 16 bytes that include at least 100 bits of entropy, or
    1. The [=public key credential source=], without its [=Credential ID=] or [=mutable items=], encrypted so only its [=managing authenticator=] can
        decrypt it. This form allows the [=authenticator=] to be nearly stateless, by having the [=[RP]=] store any necessary
        state.

        Note: [[FIDO-UAF-AUTHNR-CMDS]] includes guidance on encryption techniques under "Security Guidelines".

    [=[RPS]=] do not need to distinguish these two [=Credential ID=] forms.

: <dfn>Credential Key Pair</dfn>
: <dfn>Credential Private Key</dfn>
: <dfn>Credential Public Key</dfn>
: <dfn>User Public Key</dfn>
:: A [=credential key pair=] is a pair of asymmetric cryptographic keys generated by an [=authenticator=]
    and [=scoped=] to a specific [=[WRP]=]. It is the central part of a [=public key credential=].

    A [=credential public key=] is the public key portion of a [=credential key pair=].
    The [=credential public key=] is returned to the [=[RP]=] during a [=registration ceremony=].

    A [=credential private key=] is the private key portion of a [=credential key pair=].
    The [=credential private key=] is bound to a particular [=authenticator=] - its [=managing authenticator=] -
    and is expected to never be exposed to any other party, not even to the owner of the [=authenticator=].

    Note that in the case of [=self
    attestation=], the [=credential key pair=] is also used as the [=attestation key pair=], see [=self attestation=]
    for details.

    Note: The [=credential public key=] is referred to as the [=user public key=] in FIDO UAF [[UAFProtocol]], and in FIDO U2F
    [[FIDO-U2F-Message-Formats]] and some parts of this specification that relate to it.

: <dfn>Credential Properties</dfn>
:: A [=credential property=] is some characteristic property of a [=public key credential source=], such as whether it is a
    [=client-side discoverable credential=] or a [=server-side credential=].

: <dfn>Credential Record</dfn>
:: In order to implement the algorithms defined in [[#sctn-rp-operations]],
    the [=[RP]=] MUST store some properties of registered [=public key credential sources=].
    The [=credential record=] [=struct=] is an abstraction of these properties stored in a [=user account=].
    A&nbsp;credential record is created during a [=registration ceremony=] and used in subsequent [=authentication ceremonies=].
    [=[RPS]=] MAY delete credential records as necessary or when requested by users.

    The following [=struct/items=] are RECOMMENDED in order to implement all steps of
    [[#sctn-registering-a-new-credential]] and [[#sctn-verifying-assertion]] as defined:

    <dl dfn-for="credential record" dfn-type="abstract-op">
        :   <dfn>type</dfn>
        ::  The [=public key credential source/type=] of the [=public key credential source=].

        :   <dfn>id</dfn>
        ::  The [=Credential ID=] of the [=public key credential source=].

        :   <dfn>publicKey</dfn>
        ::  The [=credential public key=] of the [=public key credential source=].

        :   <dfn>signCount</dfn>
        ::  The latest value of the [=authData/signCount|signature counter=] in the [=authenticator data=]
            from any [=ceremony=] using the [=public key credential source=].

        :   <dfn>transports</dfn>
        ::  The value returned from {{AuthenticatorAttestationResponse/getTransports()}}
            when the [=public key credential source=] was [=registration|registered=].

            Note: Modifying or removing [=list/items=] from the value returned from {{AuthenticatorAttestationResponse/getTransports()}}
            could negatively impact user experience, or even prevent use of the corresponding credential.

        :   <dfn>uvInitialized</dfn>
        ::  A Boolean value indicating whether any [=credential=] from this [=public key credential source=]
            has had the [=authData/flags/UV=] [=flag=] set.

            When this is [TRUE], the [=[RP]=] MAY consider the [=authData/flags/UV=] [=flag=]
            as an [=authentication factor=] in [=authentication ceremonies=].
            For example, a [=[RP]=] might skip a password prompt if [$credential record/uvInitialized$] is [TRUE]
            and the [=authData/flags/UV=] [=flag=] is set, even when [=user verification=] was not required.

            When this is [FALSE], including an [=authentication ceremony=] where it would be updated to [TRUE],
            the [=authData/flags/UV=] [=flag=] MUST NOT be relied upon as an [=authentication factor=].
            This is because the first time a [=public key credential source=] sets the [=authData/flags/UV=] [=flag=] to 1,
            there is not yet any trust relationship established between the [=[RP]=] and the [=authenticator=]'s [=user verification=].
            Therefore, updating [$credential record/uvInitialized$] from [FALSE] to [TRUE]
            SHOULD require authorization by an additional [=authentication factor=] equivalent to WebAuthn [=user verification=].

        :   <dfn>backupEligible</dfn>
        ::  The value of the [=authData/flags/BE=] [=flag=] when the [=public key credential source=] was created.

        :   <dfn>backupState</dfn>
        ::  The latest value of the [=authData/flags/BS=] [=flag=] in the [=authenticator data=]
            from any [=ceremony=] using the [=public key credential source=].
    </dl>

    The following [=struct/items=] are OPTIONAL:

    <dl dfn-for="credential record" dfn-type="abstract-op">
        :   <dfn>attestationObject</dfn>
        ::  The value of the {{AuthenticatorAttestationResponse/attestationObject}} attribute
            when the [=public key credential source=] was [=registration|registered=].
            Storing this enables the [=[RP]=] to reference the credential's [=attestation statement=] at a later time.

        :   <dfn>attestationClientDataJSON</dfn>
        ::  The value of the {{AuthenticatorResponse/clientDataJSON}} attribute
            when the [=public key credential source=] was [=registration|registered=].
            Storing this in combination with the above [$credential record/attestationObject$] [=struct/item=]
            enables the [=[RP]=] to re-verify the [=attestation signature=] at a later time.
    </dl>

    [=WebAuthn extensions=] MAY define additional [=struct/items=] needed to process the extension.
    [=[RPS]=] MAY also include any additional [=struct/items=] as needed,
    and MAY omit any [=struct/items=] not needed for their implementation.

    The <dfn>credential descriptor for a credential record</dfn> is a {{PublicKeyCredentialDescriptor}} value with the contents:

    :   {{PublicKeyCredentialDescriptor/type}}
    ::  The [$credential record/type$] of the [=credential record=].

    :   {{PublicKeyCredentialDescriptor/id}}
    ::  The [$credential record/id$] of the [=credential record=].

    :   {{PublicKeyCredentialDescriptor/transports}}
    ::  The [$credential record/transports$] of the [=credential record=].

: <dfn>Generating Authenticator</dfn>
:: The Generating Authenticator is the authenticator involved in the [=authenticatorMakeCredential=] operation resulting
    in the creation of a given [=public key credential source=]. The [=generating authenticator=] is the same as the [=managing authenticator=]
    for [=single-device credentials=]. For [=multi-device credentials=], the generating authenticator may or may not be the same as the
    current [=managing authenticator=] participating in a given [=authentication=] operation.

: <dfn lt="human palatability|human-palatable">Human Palatability</dfn>
:: An identifier that is [=human-palatable=] is intended to be rememberable and reproducible by typical human
    users, in contrast to identifiers that are, for example, randomly generated sequences of bits [[EduPersonObjectClassSpec]].

: <dfn>Non-Discoverable Credential</dfn>
:: This is a [=credential=] whose [=credential ID=] must be provided in {{PublicKeyCredentialRequestOptions/allowCredentials}} when calling {{CredentialsContainer/get()|navigator.credentials.get()}} because it is not [=client-side discoverable credential|client-side discoverable=]. See also [=server-side credentials=].

: <dfn>Registrable Origin Label</dfn>
:: The first [=domain label=] of the [=registrable domain=] of a [=domain=],
    or null if the [=registrable domain=] is null.
    For example, the [=registrable origin label=] of both `example.co.uk` and `www.example.de` is `example`
    if both `co.uk` and `de` are [=public suffixes=].

: <dfn>Public Key Credential</dfn>
:: Generically, a *credential* is data one entity presents to another in order to *authenticate* the former to the latter
    [[RFC4949]]. The term [=public key credential=] refers to one of: a [=public key credential source=], the
    possibly-[=attestation|attested=] [=credential public key=] corresponding to a [=public key credential source=], or an
    [=authentication assertion=]. Which one is generally determined by context.

    <div class="note">
        <span class="marker">Note:</span>
        This is a [=willful violation=] of [[RFC4949]]. In English, a "credential" is both a) the thing presented to prove
        a statement and b) intended to be used multiple times. It's impossible to achieve both criteria securely with a single
        piece of data in a public key system. [[RFC4949]] chooses to define a credential as the thing that can be used multiple
        times (the public key), while this specification gives "credential" the English term's flexibility. This specification
        uses more specific terms to identify the data related to an [[RFC4949]] credential:

        : "Authentication information" (possibly including a private key)
        :: [=Public key credential source=]
        : "Signed value"
        :: [=Authentication assertion=]
        : [[RFC4949]] "credential"
        :: [=Credential public key=] or [=attestation object=]
    </div>

    At [=registration=] time, the [=authenticator=] creates an asymmetric key pair, and stores its [=credential private
    key|private key portion=] and information from the [=[RP]=] into a [=public key credential source=]. The [=credential public
    key|public key portion=] is returned to the [=[RP]=], which then stores it in the active [=user account=].
    Subsequently, only that [=[RP]=], as identified by its [=RP ID=], is able to employ the [=public key credential=] in
    [=authentication|authentication ceremonies=], via the {{CredentialsContainer/get()}} method. The [=[RP]=] uses its stored
    copy of the [=credential public key=] to verify the resultant [=authentication assertion=].

: <dfn>Public Key Credential Source</dfn>
:: A [=credential source=] ([[CREDENTIAL-MANAGEMENT-1]]) used by an [=authenticator=] to generate [=authentication assertions=]. A [=public key credential source=] consists of a [=struct=] with the following [=struct/items=]:

    <dl dfn-for="public key credential source">
        :   <dfn>type</dfn>
        ::  whose value is of {{PublicKeyCredentialType}}, defaulting to {{public-key}}.

        :   <dfn>id</dfn>
        ::  A [=Credential ID=].

        :   <dfn>privateKey</dfn>
        ::  The [=credential private key=].

        :   <dfn>rpId</dfn>
        ::  The [=Relying Party Identifier=], for the [=[RP]=] this [=public key credential source=] is [=scoped=] to.
            This is determined by the <code>{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code>
            parameter of the {{CredentialsContainer/create()}} operation.

        :   <dfn>userHandle</dfn>
        ::  The [=user handle=] associated when this [=public key credential source=] was created. This [=struct/item=] is
            nullable, however [=user handle=] MUST always be populated for [=discoverable credentials=].

        :   <dfn>otherUI</dfn>
        ::  OPTIONAL other information used by the [=authenticator=] to inform its UI. For example, this might include the user's
            {{PublicKeyCredentialUserEntity/displayName}}. [=public key credential source/otherUI=] is a <dfn>mutable item</dfn> and SHOULD NOT be bound to the
            [=public key credential source=] in a way that prevents [=public key credential source/otherUI=] from being updated.
    </dl>

    The [=authenticatorMakeCredential=] operation creates a [=public key credential source=] [=bound credential|bound=] to a <dfn for="public key
    credential source">managing authenticator</dfn> and returns the [=credential public key=] associated with its [=credential
    private key=]. The [=[RP]=] can use this [=credential public key=] to verify the [=authentication assertions=] created by
    this [=public key credential source=].

: <dfn>Rate Limiting</dfn>
:: The process (also known as throttling) by which an authenticator implements controls against brute force attacks by limiting
    the number of consecutive failed authentication attempts within a given period of time. If the limit is reached, the
    authenticator should impose a delay that increases exponentially with each successive attempt, or disable the current
    authentication modality and offer a different [=authentication factor=] if available. [=Rate limiting=] is often implemented as an
    aspect of [=user verification=].

: <dfn>Registration</dfn>
: <dfn>Registration Ceremony</dfn>
:: The [=ceremony=] where a user, a [=[RP]=], and the user's [=client platform=] (containing or connected to at least one
    [=authenticator=]) work in concert to create a [=public key credential=] and associate it with a [=user account=].
    Note that this includes employing a [=test of user presence=] or [=user verification=].
    After a successful [=registration ceremony=], the user can be authenticated by an [=authentication ceremony=].

    The WebAuthn [=registration ceremony=] is defined in [[#sctn-registering-a-new-credential]],
    and is initiated by the [=[RP]=] invoking a <code>{{CredentialsContainer/create()|navigator.credentials.create()}}</code> operation
    with a {{CredentialCreationOptions/publicKey}} argument.
    See [[#sctn-api]] for an introductory overview and [[#sctn-sample-registration]] for implementation examples.

: <dfn>[RP]</dfn>
: <dfn>[WRP]</dfn>
:: The entity whose <dfn>web application</dfn> utilizes the [[#sctn-api|Web Authentication API]] to [=registration|register=] and
    [=authentication|authenticate=] users.

    A [=[RP]=] implementation typically consists of both some client-side script
    that invokes the [=Web Authentication API=] in the [=client=],
    and a server-side component that executes the [[#sctn-rp-operations|[RP] operations]] and other application logic.
    Communication between the two components MUST use HTTPS or equivalent transport security,
    but is otherwise beyond the scope of this specification.

        Note: While the term [=[RP]=] is also often used in other contexts (e.g., X.509 and OAuth), an entity acting as a [=[RP]=] in one
        context is not necessarily a [=[RP]=] in other contexts. In this specification, the term [=[WRP]=] is often shortened
        to be just [=[RP]=], and explicitly refers to a [=[RP]=] in the WebAuthn context. Note that in any concrete instantiation
        a WebAuthn context may be embedded in a broader overall context, e.g., one based on OAuth.


: <dfn>Relying Party Identifier</dfn>
: <dfn>RP ID</dfn>
:: In the context of the [=web authentication api|WebAuthn API=], a [=relying party identifier=] is a [=valid domain string=] identifying the [=[WRP]=] on whose behalf a given [=registration=] or
    [=authentication|authentication ceremony=] is being performed. A [=public key credential=] can only be used for
    [=authentication=] with the same entity (as identified by [=RP ID=]) it was registered with.

    By default, the [=RP ID=] for a
    WebAuthn operation is set to the caller's [=environment settings object/origin=]'s [=effective domain=]. This default MAY be
    overridden by the caller, as long as the caller-specified [=RP ID=] value [=is a registrable domain suffix of or is equal
    to=] the caller's [=environment settings object/origin=]'s [=effective domain=]. See also [[#sctn-createCredential]] and
    [[#sctn-getAssertion]].

    An [=RP ID=] is based on a [=origin/host=]'s [=domain=] name.
    It does not itself include a [=origin/scheme=] or [=port=], as an [=origin=] does.
    The [=RP ID=] of a [=public key credential=] determines its <dfn>scope</dfn>.
    I.e., it <dfn>determines the set of origins on which the public key credential may be exercised</dfn>, as follows:

        - The [=RP ID=] must be equal to the [=determines the set of origins on which the public key credential may be exercised|origin=]'s [=effective domain=],
            or a [=is a registrable domain suffix of or is equal to|registrable domain suffix=] of the
            [=determines the set of origins on which the public key credential may be exercised|origin=]'s [=effective domain=].
        - One of the following must be true:
            - The [=determines the set of origins on which the public key credential may be exercised|origin=]'s [=origin/scheme=] is `https`.
            - The [=determines the set of origins on which the public key credential may be exercised|origin=]'s [=origin/host=] is `localhost`
                and its [=origin/scheme=] is `http`.
        - The [=determines the set of origins on which the public key credential may be exercised|origin=]'s [=port=] is unrestricted.

    For example, given a [=[RP]=] whose origin is `https://login.example.com:1337`, then the following [=RP ID=]s are valid:
    `login.example.com` (default) and `example.com`, but not `m.login.example.com` and not `com`.
    Another example of a valid origin is `http://localhost:8000`, due to the origin being `localhost`.

    This is done in order to match the behavior of pervasively deployed ambient credentials (e.g., cookies, [[RFC6265]]).
    Please note that this is a greater relaxation of "same-origin" restrictions than what
    [=document.domain=]'s setter provides.

    These restrictions on origin values apply to [=WebAuthn Clients=].

    Other specifications mimicking the [=web authentication api|WebAuthn API=] to enable WebAuthn [=public key credentials=] on non-Web platforms (e.g. native mobile applications), MAY define different rules for binding a caller to a [=Relying Party Identifier=]. Though, the [=RP ID=] syntaxes MUST conform to either [=valid domain strings=] or URIs [[!RFC3986]] [[!URL]].

: <dfn>Server-side Public Key Credential Source</dfn>
: <dfn>Server-side Credential</dfn>
: \[DEPRECATED] <dfn>Non-Resident Credential</dfn>
:: Note: Historically, [=server-side credentials=] have been known as [=non-resident credentials=].
    For backwards compatibility purposes, the various [=web authentication api|WebAuthn API=] and
    [=Authenticator Model=] components
    with various forms of `resident` within their names have not been changed.

    A [=Server-side Public Key Credential Source=], or [=Server-side Credential=] for short,
    is a [=public key credential source=] that is only usable in an [=authentication ceremony=]
    when the [=[RP]=] supplies its [=credential ID=] in {{CredentialsContainer/get()|navigator.credentials.get()}}'s
    {{PublicKeyCredentialRequestOptions/allowCredentials}} argument. This means that the [=[RP]=] must
    manage the credential's storage and discovery, as well as be able to first identify the user in order to
    discover the [=credential IDs=] to supply in the
    {{CredentialsContainer/get()|navigator.credentials.get()}} call.

    [=Client-side=] storage of the [=public key credential source=]
    is not required for a [=server-side credential=].
    This is in contrast to a [=client-side discoverable credential=],
    which instead does not require the user to first be identified in order to provide the user's [=credential ID=]s
    to a {{CredentialsContainer/get()|navigator.credentials.get()}} call.

    See also: [=server-side credential storage modality=] and [=non-discoverable credential=].

: <dfn>Test of User Presence</dfn>
:: A [=test of user presence=] is a simple form of [=authorization gesture=] and technical process where a user interacts with
    an [=authenticator=] by (typically) simply touching it (other modalities may also exist), yielding a Boolean result. Note
    that this does not constitute [=user verification=] because a [=test of user presence|user presence test=], by definition,
    is not capable of [=biometric recognition=], nor does it involve the presentation of a shared secret such as a password or
    PIN.

: <dfn>User Account</dfn>
:: In the context of this specification,
    a [=user account=] denotes the mapping of a set of [=credentials=] [[CREDENTIAL-MANAGEMENT-1]]
    to a (sub)set of a [=[RP]=]'s resources, as maintained and authorized by the [=[RP]=].
    The [=[RP]=] maps a given [=public key credential=] to a [=user account=]
    by assigning a [=user account=]-specific value to the credential's [=user handle=]
    and storing a [=credential record=] for the credential in the [=user account=].
    This mapping, the set of credentials, and their authorizations, may evolve over time.
    A given [=user account=] might be accessed by one or more natural persons (also known as "users"),
    and one natural person might have access to one or more [=user accounts=],
    depending on actions of the user(s) and the [=[RP]=].

: <dfn>User Consent</dfn>
:: User consent means the user agrees with what they are being asked, i.e., it encompasses reading and understanding prompts.
    An [=authorization gesture=] is a [=ceremony=] component often employed to indicate [=user consent=].

: <dfn>User Handle</dfn>
:: A user handle is an identifier for a [=user account=], specified by the [=[RP]=] as
    <code>{{PublicKeyCredentialCreationOptions/user}}.{{PublicKeyCredentialUserEntity/id}}</code>
    during [=registration=].
    [=Discoverable credentials=] store this identifier and MUST return it as
    <code>{{PublicKeyCredential/response}}.{{AuthenticatorAssertionResponse/userHandle}}</code>
    in [=authentication ceremonies=] started with an [=list/empty=]
    <code>{{PublicKeyCredentialRequestOptions/allowCredentials}}</code> argument.

    The main use of the [=user handle=] is to identify the [=user account=] in such [=authentication ceremonies=],
    but the [=credential ID=] could be used instead.
    The main differences are
    that the [=credential ID=] is chosen by the [=authenticator=] and is unique for each credential,
    while the [=user handle=] is chosen by the [=[RP]=] and ought to be the same
    for all [=credentials=] registered to the same [=user account=].

    [=Authenticators=] [=credentials map|map=] pairs of [=RP ID=] and [=user handle=] to [=public key credential sources=].
    As a consequence, an authenticator will store at most one [=discoverable credential=] per [=user handle=] per [=[RP]=]. Therefore
    a secondary use of the [=user handle=] is to allow [=authenticators=] to know when to replace an existing [=discoverable credential=]
    with a new one during the [=registration ceremony=].

    A user handle is an opaque [=byte sequence=] with a maximum size of 64 bytes, and is not meant to be displayed to the user.
    It MUST NOT contain personally identifying information, see [[#sctn-user-handle-privacy]].

: <dfn id=concept-user-present>User Present</dfn>
:: Upon successful completion of a [=test of user presence|user presence test=], the user is said to be
    "[=user present|present=]".

: <dfn>User Verification</dfn>
:: The technical process by which an [=authenticator=] <em>locally authorizes</em> the invocation of the
    [=authenticatorMakeCredential=] and [=authenticatorGetAssertion=] operations. [=User verification=] MAY be instigated
    through various [=authorization gesture=] modalities; for example, through a touch plus pin code, password entry, or
    [=biometric recognition=] (e.g., presenting a fingerprint) [[ISOBiometricVocabulary]]. The intent is to
    distinguish individual users.
    See also [[#sctn-authentication-factor-capability]].

    Note that [=user verification=] does not give the [=[RP]=] a concrete identification of the user,
    but when 2 or more ceremonies with [=user verification=] have been done with that [=credential=]
    it expresses that it was the same user that performed all of them.
    The same user might not always be the same natural person, however,
    if multiple natural persons share access to the same [=authenticator=].

    Note: Distinguishing natural persons depends in significant part upon the [=client platform=]'s
    and [=authenticator=]'s capabilities.
    For example, some devices are intended to be used by a single individual,
    yet they may allow multiple natural persons to enroll fingerprints or know the same PIN
    and thus access the same [=user account=](s) using that device.

    NOTE: Invocation of the [=authenticatorMakeCredential=] and [=authenticatorGetAssertion=] operations
    implies use of key material managed by the authenticator.

    For security, [=user verification=] and use of [=credential private keys=]
    MUST all occur within the logical security boundary defining the [=authenticator=].

    [=User verification=] procedures MAY implement [=rate limiting=] as a protection against brute force attacks.

: <dfn id=concept-user-verified>User Verified</dfn>
:: Upon successful completion of a [=user verification=] process, the user is said to be "[=user verified|verified=]".


# <dfn>Web Authentication API</dfn> # {#sctn-api}

This section normatively specifies the API for creating and using [=public key credentials=]. The basic
idea is that the credentials belong to the user and are [=managing authenticator|managed=] by a [=[WAA]=], with which the [=[WRP]=] interacts through the [=client platform=]. [=[RP]=] scripts can (with the [=user consent|user's consent=]) request the
browser to create a new credential for future use by the [=[RP]=]. See <a href="#fig-registration">Figure <span class="figure-num-following"></span></a>, below.


<figure id="fig-registration">
    <img no-autosize src="images/webauthn-registration-flow-01.svg">
    <figcaption>Registration Flow</figcaption>
</figure>


Scripts can also request the user’s permission to perform
[=authentication=] operations with an existing credential. See <a href="#fig-authentication">Figure <span class="figure-num-following"></span></a>, below.


<figure id="fig-authentication">
    <img no-autosize src="images/webauthn-authentication-flow-01.svg">
    <figcaption>Authentication Flow</figcaption>
</figure>


All such operations are performed in the authenticator and are mediated by
the [=client platform=] on the user's behalf. At no point does the script get access to the credentials themselves; it only
gets information about the credentials in the form of objects.

In addition to the above script interface, the authenticator MAY implement (or come with client software that implements) a user
interface for management. Such an interface MAY be used, for example, to reset the authenticator to a clean state or to inspect
the current state of the authenticator. In other words, such an interface is similar to the user interfaces provided by browsers
for managing user state such as history, saved passwords, and cookies. Authenticator management actions such as credential
deletion are considered to be the responsibility of such a user interface and are deliberately omitted from the API exposed to
scripts.

The security properties of this API are provided by the client and the authenticator working together. The authenticator, which
holds and [=managing authenticator|manages=] credentials, ensures that all operations are [=scoped=] to a particular [=origin=], and cannot be replayed against
a different [=origin=], by incorporating the [=origin=] in its responses. Specifically, as defined in [[#sctn-authenticator-ops]],
the full [=origin=] of the requester is included, and signed over, in the [=attestation object=] produced when a new credential
is created as well as in all assertions produced by WebAuthn credentials.

Additionally, to maintain user privacy and prevent malicious [=[RPS]=] from probing for the presence of [=public key
credentials=] belonging to other [=[RPS]=], each [=public key credential|credential=] is also [=scoped=] to a [=Relying Party
Identifier=], or [=RP ID=]. This [=RP ID=] is provided by the client to the [=authenticator=] for all operations, and the
[=authenticator=] ensures that [=public key credential|credentials=] created by a [=[RP]=] can only be used in operations
requested by the same [=RP ID=]. Separating the [=origin=] from the [=RP ID=] in this way allows the API to be used in cases
where a single [=[RP]=] maintains multiple [=origins=].

The client facilitates these security measures by providing the [=[RP]=]'s [=origin=] and [=RP ID=] to the [=authenticator=] for
each operation. Since this is an integral part of the WebAuthn security model, user agents only expose this API to callers in
[=secure contexts=].
For web contexts in particular,
this only includes those accessed via a secure transport (e.g., TLS) established without errors.

The Web Authentication API is defined by the union of the Web IDL fragments presented in the following sections. A combined IDL
listing is given in the [[#idl-index]].

## <dfn interface>PublicKeyCredential</dfn> Interface ## {#iface-pkcredential}

The {{PublicKeyCredential}} interface inherits from {{Credential}} [[!CREDENTIAL-MANAGEMENT-1]], and contains the attributes
that are returned to the caller when a new credential is created, or a new assertion is requested.

<xmp class="idl">
    [SecureContext, Exposed=Window]
    interface PublicKeyCredential : Credential {
        [SameObject] readonly attribute ArrayBuffer              rawId;
        [SameObject] readonly attribute AuthenticatorResponse    response;
        readonly attribute DOMString?                            authenticatorAttachment;
        AuthenticationExtensionsClientOutputs getClientExtensionResults();
        static Promise<boolean> isConditionalMediationAvailable();
        PublicKeyCredentialJSON toJSON();
    };
</xmp>
<dl dfn-type="attribute" dfn-for="PublicKeyCredential">
    :   {{Credential/id}}
    ::  This attribute is inherited from {{Credential}}, though {{PublicKeyCredential}} overrides {{Credential}}'s getter,
        instead returning the [=base64url encoding=] of the data contained in the object's
        {{PublicKeyCredential/[[identifier]]}} [=internal slot=].

    :   {{PublicKeyCredential/rawId}}
    ::  This attribute returns the {{ArrayBuffer}} contained in the {{PublicKeyCredential/[[identifier]]}} internal slot.

    :   <dfn>response</dfn>
    ::  This attribute contains the [=authenticator=]'s response to the client's request to either create a [=public key
        credential=], or generate an [=authentication assertion=]. If the {{PublicKeyCredential}} is created in response to
        {{CredentialsContainer/create()}}, this attribute's value will be an {{AuthenticatorAttestationResponse}}, otherwise,
        the {{PublicKeyCredential}} was created in response to {{CredentialsContainer/get()}}, and this attribute's value
        will be an {{AuthenticatorAssertionResponse}}.

    :   <dfn>authenticatorAttachment</dfn>
    ::  This attribute reports the [=authenticator attachment modality=] in effect at the time the
        {{CredentialsContainer/create()|navigator.credentials.create()}} or
        {{CredentialsContainer/get()|navigator.credentials.get()}} methods successfully complete.
        The attribute’s value SHOULD be a member of {{AuthenticatorAttachment}}. [=[RPS]=] SHOULD treat unknown values
        as if the value were null.

        <div class="note">
        <span class="marker">Note:</span>
        If, as the result of a [=registration ceremony|registration=] or [=authentication ceremony=], {{PublicKeyCredential/authenticatorAttachment}}'s value is "cross-platform" and
        concurrently {{isUserVerifyingPlatformAuthenticatorAvailable}} returns [TRUE], then the user employed a [=roaming authenticator=] for this [=ceremony=] while there is an available
        [=platform authenticator=]. Thus the [=[RP]=] has the opportunity to prompt the user to register the available [=platform authenticator=], which may enable more streamlined user experience flows.

        An [=authenticator's=] [=authenticator attachment modality|attachment modality=] could change over time.
        For example, a mobile phone might at one time only support [=platform attachment=]
        but later receive updates to support [=cross-platform attachment=] as well.
        </div>




    :   {{PublicKeyCredential/getClientExtensionResults()}}
    ::  This operation returns the value of {{PublicKeyCredential/[[clientExtensionsResults]]}}, which is a [=map=] containing
        [=extension identifier=] → [=client extension output=] entries produced by the extension's
        [=client extension processing=].

    :   {{PublicKeyCredential/isConditionalMediationAvailable()}}
    ::  {{PublicKeyCredential}} overrides this method to indicate availability for {{CredentialMediationRequirement/conditional}}
        mediation during {{CredentialsContainer/get()|navigator.credentials.get()}}. [=[WRPS]=] SHOULD verify availability before
        attempting to set <code>|options|.{{CredentialRequestOptions/mediation}}</code> to {{CredentialMediationRequirement/conditional}}.

        Upon invocation, a promise is returned that resolves with a value of [TRUE] if {{CredentialMediationRequirement/conditional}}
        [=user mediation=] is available, or [FALSE] otherwise.

        This method has no arguments and returns a promise to a Boolean value.

        The {{ClientCapability/conditionalGet}} capability is equivalent to this promise resolving to [TRUE].

        Note: If this method is not present, {{CredentialMediationRequirement/conditional}} [=user mediation=] is not available for
        {{CredentialsContainer/get()|navigator.credentials.get()}}.

        Note: This method does *not* indicate
        whether or not {{CredentialMediationRequirement/conditional}} [=user mediation=] is available
        in {{CredentialsContainer/create()|navigator.credentials.create()}}.
        For that, see the {{ClientCapability/conditionalCreate}} capability in {{PublicKeyCredential/getClientCapabilities()}}.

    :   {{PublicKeyCredential/toJSON()}}
    ::  This operation returns {{RegistrationResponseJSON}} or {{AuthenticationResponseJSON}},
        which are [=JSON type=] representations mirroring {{PublicKeyCredential}}, suitable for submission to a
        [=[RP]=] server as an `application/json` payload. The [=client=] is in charge of
        [serializing values to JSON types as usual](https://webidl.spec.whatwg.org/#idl-tojson-operation),
        but MUST take additional steps to first encode any {{ArrayBuffer}} values to {{DOMString}} values
        using [=base64url encoding=].

        The
        {{RegistrationResponseJSON/clientExtensionResults|RegistrationResponseJSON.clientExtensionResults}} or
        {{AuthenticationResponseJSON/clientExtensionResults|AuthenticationResponseJSON.clientExtensionResults}}
        member MUST be set to the output of {{PublicKeyCredential/getClientExtensionResults()}},
        with any {{ArrayBuffer}} values encoded to {{DOMString}} values using
        [=base64url encoding=]. This MAY include {{ArrayBuffer}} values from extensions registered
        in the IANA "WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] but not
        defined in [[#sctn-extensions]].

        The {{AuthenticatorAttestationResponseJSON/transports|AuthenticatorAttestationResponseJSON.transports}}
        member MUST be set to the output of {{AuthenticatorAttestationResponse/getTransports()}}.

        The {{AuthenticatorAttestationResponseJSON/publicKey|AuthenticatorAttestationResponseJSON.publicKey}}
        member MUST be set to the output of {{AuthenticatorAttestationResponse/getPublicKey()}}.

        The {{AuthenticatorAttestationResponseJSON/publicKeyAlgorithm|AuthenticatorAttestationResponseJSON.publicKeyAlgorithm}}
        member MUST be set to the output of {{AuthenticatorAttestationResponse/getPublicKeyAlgorithm()}}.
</dl>

<xmp class="idl">
    typedef DOMString Base64URLString;
    // The structure of this object will be either
    // RegistrationResponseJSON or AuthenticationResponseJSON
    typedef object PublicKeyCredentialJSON;

    dictionary RegistrationResponseJSON {
        required DOMString id;
        required Base64URLString rawId;
        required AuthenticatorAttestationResponseJSON response;
        DOMString authenticatorAttachment;
        required AuthenticationExtensionsClientOutputsJSON clientExtensionResults;
        required DOMString type;
    };

    dictionary AuthenticatorAttestationResponseJSON {
        required Base64URLString clientDataJSON;
        required Base64URLString authenticatorData;
        required sequence<DOMString> transports;
        // The publicKey field will be missing if pubKeyCredParams was used to
        // negotiate a public-key algorithm that the user agent doesn't
        // understand. (See section “Easily accessing credential data” for a
        // list of which algorithms user agents must support.) If using such an
        // algorithm then the public key must be parsed directly from
        // attestationObject or authenticatorData.
        Base64URLString publicKey;
        required COSEAlgorithmIdentifier publicKeyAlgorithm;
        // This value contains copies of some of the fields above. See
        // section “Easily accessing credential data”.
        required Base64URLString attestationObject;
    };

    dictionary AuthenticationResponseJSON {
        required DOMString id;
        required Base64URLString rawId;
        required AuthenticatorAssertionResponseJSON response;
        DOMString authenticatorAttachment;
        required AuthenticationExtensionsClientOutputsJSON clientExtensionResults;
        required DOMString type;
    };

    dictionary AuthenticatorAssertionResponseJSON {
        required Base64URLString clientDataJSON;
        required Base64URLString authenticatorData;
        required Base64URLString signature;
        Base64URLString userHandle;
    };

    dictionary AuthenticationExtensionsClientOutputsJSON {
    };
</xmp>

<dl dfn-type="attribute" dfn-for="PublicKeyCredential">
    :   <dfn>\[[type]]</dfn>
    ::  The {{PublicKeyCredential}} [=interface object=]'s {{Credential/[[type]]}} [=internal slot=]'s value is the string
        "`public-key`".

        Note: This is reflected via the {{Credential/type}} attribute getter inherited from {{Credential}}.

    :   <dfn>\[[discovery]]</dfn>
    ::  The {{PublicKeyCredential}} [=interface object=]'s {{Credential/[[discovery]]}} [=internal slot=]'s value is
        "{{Credential/[[discovery]]/remote}}".

    :   <dfn>\[[identifier]]</dfn>
    ::  This [=internal slot=] contains the [=credential ID=], chosen by the authenticator.
        The [=credential ID=] is used to look up credentials for use, and is therefore expected to be globally unique
        with high probability across all credentials of the same type, across all authenticators.

        This API does not constrain the format of this identifier,
        except that it MUST NOT be longer than 1023 bytes and MUST be sufficient for the [=authenticator=] to uniquely select a key.
        For example, an authenticator without on-board storage may create identifiers containing a [=credential private key=]
        wrapped with a symmetric key that is burned into the authenticator.

    :   <dfn>\[[clientExtensionsResults]]</dfn>
    ::  This [=internal slot=] contains the results of processing client extensions requested by the [=[RP]=] upon the
        [=[RP]=]'s invocation of either {{CredentialsContainer/create()|navigator.credentials.create()}} or
        {{CredentialsContainer/get()|navigator.credentials.get()}}.
</dl>

{{PublicKeyCredential}}'s [=interface object=] inherits {{Credential}}'s implementation of
{{Credential/[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)}}, and defines its own
implementation of each of {{PublicKeyCredential/[CREATE-METHOD]}}, {{PublicKeyCredential/[DISCOVER-METHOD]}}, and
{{PublicKeyCredential/[[Store]](credential, sameOriginWithAncestors)}}.

Calling {{CredentialsContainer}}'s {{CredentialsContainer/preventSilentAccess()}} method
will have no effect on {{PublicKeyCredential}} credentials, since they always require user interaction.


### `CredentialCreationOptions` Dictionary Extension ### {#sctn-credentialcreationoptions-extension}

To support registration via {{CredentialsContainer/create()|navigator.credentials.create()}}, this document extends
the {{CredentialCreationOptions}} dictionary as follows:

<xmp class="idl">
    partial dictionary CredentialCreationOptions {
        PublicKeyCredentialCreationOptions      publicKey;
    };
</xmp>

### `CredentialRequestOptions` Dictionary Extension ### {#sctn-credentialrequestoptions-extension}

To support obtaining assertions via {{CredentialsContainer/get()|navigator.credentials.get()}}, this document extends the
{{CredentialRequestOptions}} dictionary as follows:

<xmp class="idl">
    partial dictionary CredentialRequestOptions {
        PublicKeyCredentialRequestOptions      publicKey;
    };
</xmp>


### Create a New Credential - PublicKeyCredential's <dfn for="PublicKeyCredential" method>[CREATE-METHOD-DEF]</dfn> Internal Method ### {#sctn-createCredential}

<div link-for-hint="PublicKeyCredential/[CREATE-METHOD]">
{{PublicKeyCredential}}'s [=interface object=]'s implementation of the {{Credential/[CREATE-METHOD]}} [=internal method=] [[!CREDENTIAL-MANAGEMENT-1]] allows
[=[WRP]=] scripts to call {{CredentialsContainer/create()|navigator.credentials.create()}} to request the creation of a new
[=public key credential source=], [=bound credential|bound=] to an [=authenticator=].

By setting <code>|options|.{{CredentialCreationOptions/mediation}}</code> to {{CredentialMediationRequirement/conditional}},
[=[RPS]=] can indicate that they would like to register a credential without prominent modal UI if the user has already consented to create a credential.
The [=[RP]=] SHOULD first use {{PublicKeyCredential/getClientCapabilities()}}
to check that the [=client=] supports the {{ClientCapability/conditionalCreate}} capability
in order to prevent a user-visible error in case this feature is not available.
The client MUST set BOTH |requireUserPresence| and |requireUserVerification| to |FALSE| when <code>|options|.{{CredentialCreationOptions/mediation}}</code> is set to {{CredentialMediationRequirement/conditional}}
unless they may be explicitly performed during the ceremony.

Any {{CredentialsContainer/create()|navigator.credentials.create()}} operation can be aborted by leveraging the {{AbortController}};
see [[dom#abortcontroller-api-integration]] for detailed instructions.


This [=internal method=] accepts three arguments:

<dl dfn-type="argument" dfn-for="PublicKeyCredential/[CREATE-METHOD]">

    :   <dfn>origin</dfn>
    ::  This argument is the [=relevant settings object=]'s [=environment settings object/origin=], as determined by the
        calling {{CredentialsContainer/create()}} implementation.

    :   <dfn>options</dfn>
    ::  This argument is a {{CredentialCreationOptions}} object whose
        <code>|options|.{{CredentialCreationOptions/publicKey}}</code> member contains a {{PublicKeyCredentialCreationOptions}}
        object specifying the desired attributes of the to-be-created [=public key credential=].

    :   <dfn>sameOriginWithAncestors</dfn>
    ::  This argument is a Boolean value which is [TRUE] if and only if the caller's [=environment settings object=] is
        [=same-origin with its ancestors=]. It is [FALSE] if caller is cross-origin.

        Note: Invocation of this [=internal method=] indicates that it was allowed by
        [=permissions policy=], which is evaluated at the [[!CREDENTIAL-MANAGEMENT-1]] level.
        See [[#sctn-permissions-policy]].
</dl>

Note: <strong>This algorithm is synchronous:</strong> the {{Promise}} resolution/rejection is handled by
{{CredentialsContainer/create()|navigator.credentials.create()}}.

All {{BufferSource}} objects used in this algorithm MUST be snapshotted when the algorithm begins, to
avoid potential synchronization issues. Implementations SHOULD [=get a copy of the bytes held
by the buffer source=] and use that copy for relevant portions of the algorithm.

When this method is invoked, the user agent MUST execute the following algorithm:

1. Assert: <code>|options|.{{CredentialCreationOptions/publicKey}}</code> is present.

1. If <var ignore>sameOriginWithAncestors</var> is [FALSE]:

    1. If <code>|options|.{{CredentialCreationOptions/mediation}}</code> is present with the value
        {{CredentialMediationRequirement/conditional}}:

        1. Throw a "{{NotAllowedError}}" {{DOMException}}

    1. If the [=relevant global object=], as determined by the calling
        {{CredentialsContainer/create()}} implementation, does not have
        [=transient activation=]:

        1. Throw a "{{NotAllowedError}}" {{DOMException}}.

    1. [=Consume user activation=] of the [=relevant global object=].

    1. If the [=origin=] that is creating a credential is different from the [=top-level origin=] of the [=relevant global object=]
        (i.e., is a different origin than the user can see in the address bar),
        the [=client=] SHOULD make this fact clear to the user.

1. Let |pkOptions| be the value of <code>|options|.{{CredentialCreationOptions/publicKey}}</code>.

1. If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/timeout}}</code> is present, check if its value lies within a
    reasonable range as defined by the [=client=] and if not, correct it to the closest value lying within that range. Set a timer
    |lifetimeTimer| to this adjusted value. If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/timeout}}</code> is not
    present, then set |lifetimeTimer| to a [=client=]-specific default.

        See the [=recommended range and default for a WebAuthn ceremony timeout=]
        for guidance on deciding a reasonable range and default for <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/timeout}}</code>.

        The [=client=] SHOULD take cognitive guidelines into considerations regarding timeout for users with special needs.

1. If the length of <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/user}}.{{PublicKeyCredentialUserEntity/id}}</code> is not between 1 and 64 bytes (inclusive) then throw a {{TypeError}}.

1. Let |callerOrigin| be {{PublicKeyCredential/[CREATE-METHOD]/origin}}. If |callerOrigin| is an [=opaque origin=], throw a "{{NotAllowedError}}" {{DOMException}}.

1. Let |effectiveDomain| be the |callerOrigin|'s [=effective domain=].
    If [=effective domain=] is not a [=valid domain=], then throw a
    "{{SecurityError}}" {{DOMException}}.

    Note: An [=effective domain=] may resolve to a [=host=], which can be represented in various manners,
        such as [=domain=], [=ipv4 address=], [=ipv6 address=], [=opaque host=], or [=empty host=].
        Only the [=domain=] format of [=host=] is allowed here. This is for simplification and also
        is in recognition of various issues with using direct IP address identification in concert
        with PKI-based security.

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list :-/
-->
    <li id='CreateCred-DetermineRpId'>

        If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code>
            <dl class="switch">

                :   is present
                ::  If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> [=is not a
                    registrable domain suffix of and is not equal to=] |effectiveDomain|, and if the client
                
                    <dl class="switch">
                        :   supports [[#sctn-related-origins|related origin requests]]
                        ::  1. Let |rpIdRequested| be the value of <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code>.

                            1. Run the [$related origins validation procedure$] with arguments |callerOrigin| and |rpIdRequested|.
                                If the result is [FALSE], throw a "{{SecurityError}}" {{DOMException}}.

                        :   does not support [[#sctn-related-origins|related origin requests]]
                        ::  throw a "{{SecurityError}}" {{DOMException}}.
                    </dl>
                    
                :   is not present
                ::  Set <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> to |effectiveDomain|.
            </dl>

        Note: <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> represents the
            caller's [=RP ID=]. The [=RP ID=] defaults to being the caller's [=environment settings object/origin=]'s
            [=effective domain=] unless the caller has explicitly set
            <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> when calling
            {{CredentialsContainer/create()}}.
    </li>

1. Let |credTypesAndPubKeyAlgs| be a new [=list=] whose [=list/items=] are pairs of {{PublicKeyCredentialType}} and
    a {{COSEAlgorithmIdentifier}}.

1. If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/pubKeyCredParams}}</code>'s [=list/size=]
    <dl class="switch">
        :   is zero
        ::  [=list/Append=] the following pairs of {{PublicKeyCredentialType}} and {{COSEAlgorithmIdentifier}} values to |credTypesAndPubKeyAlgs|:
             * {{public-key}} and <code>-7</code> ("ES256").
             * {{public-key}} and <code>-257</code> ("RS256").

        :   is non-zero
        ::  [=list/For each=] |current| of <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/pubKeyCredParams}}</code>:

            1. If <code>|current|.{{PublicKeyCredentialParameters/type}}</code> does not contain a {{PublicKeyCredentialType}} supported
                by this implementation, then [=continue=].
            1. Let |alg| be <code>|current|.{{PublicKeyCredentialParameters/alg}}</code>.
            1. [=list/Append=] the pair of <code>|current|.{{PublicKeyCredentialParameters/type}}</code> and |alg| to
                |credTypesAndPubKeyAlgs|.

            If |credTypesAndPubKeyAlgs| [=list/is empty=], throw a "{{NotSupportedError}}" {{DOMException}}.
    </dl>

1. Let |clientExtensions| be a new [=map=] and let |authenticatorExtensions| be a new [=map=].

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list -->
    <li id="CreateCred-process-extensions">
        If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/extensions}}</code> is present, then [=map/for each=]
        |extensionId| → |clientExtensionInput| of <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/extensions}}</code>:
        1. If |extensionId| is not supported by this [=client platform=] or is not a [=registration extension=], then [=continue=].

        1. [=map/Set=] |clientExtensions|[|extensionId|] to |clientExtensionInput|.

        1. If |extensionId| is not an [=authenticator extension=], then [=continue=].

        1. Let |authenticatorExtensionInput| be the ([=CBOR=]) result of running |extensionId|'s [=client extension processing=]
            algorithm on |clientExtensionInput|. If the algorithm returned an error, [=continue=].

        1. [=map/Set=] |authenticatorExtensions|[|extensionId|] to the [=base64url encoding=] of |authenticatorExtensionInput|.
    </li>

1. Let |collectedClientData| be a new {{CollectedClientData}} instance whose fields are:
    : {{CollectedClientData/type}}
    :: The string "webauthn.create".
    : {{CollectedClientData/challenge}}
    :: The [=base64url encoding=] of |pkOptions|.{{PublicKeyCredentialCreationOptions/challenge}}.
    : {{CollectedClientData/origin}}
    :: The [=ascii serialization of an origin|serialization of=] |callerOrigin|.
    : {{CollectedClientData/crossOrigin}}
    :: The inverse of the value of the
        {{PublicKeyCredential/[CREATE-METHOD]/sameOriginWithAncestors}}
        argument passed to this [=internal method=].
    : {{CollectedClientData/topOrigin}}
    :: The [=ascii serialization of an origin|serialization of=] |callerOrigin|'s [=top-level origin=] if
        the {{PublicKeyCredential/[CREATE-METHOD]/sameOriginWithAncestors}}
        argument passed to this [=internal method=] is [FALSE], else `undefined`.

1. Let |clientDataJSON| be the [=JSON-compatible serialization of client data=] constructed from |collectedClientData|.

1. Let |clientDataHash| be the [=hash of the serialized client data=] represented by |clientDataJSON|.

1. If <code>|options|.{{CredentialCreationOptions/signal}}</code> is present and [=AbortSignal/aborted=], throw
    the <code>|options|.{{CredentialCreationOptions/signal}}</code>'s [=AbortSignal/abort reason=].

1. Let |issuedRequests| be a new [=ordered set=].

1. Let |authenticators| represent a value which at any given instant is a [=set=] of [=client platform=]-specific handles, where each
    [=set/item=] identifies an [=authenticator=] presently available on this [=client platform=] at that instant.

    Note: What qualifies an [=authenticator=] as "available" is intentionally unspecified; this is meant to represent how
    [=authenticators=] can be <a href="https://en.wikipedia.org/w/index.php?title=Hot_plug">hot-plugged</a> into (e.g., via USB)
    or discovered (e.g., via NFC or Bluetooth) by the [=client=] by various mechanisms, or permanently built into the [=client=].

1. If <code>|options|.{{CredentialCreationOptions/mediation}}</code> is present with the value
     {{CredentialMediationRequirement/conditional}}:

    1. If the user agent has not recently mediated an authentication, the origin of said authentication is not |callerOrigin|, or the user
        does not consent to this type of credential creation, throw a "{{NotAllowedError}}" {{DOMException}}.

        It is up to the user agent to decide when it believes an authentication ceremony has
        been completed. That authentication ceremony MAY be performed via other means than the
        [=Web Authentication API=].

1. Consider the value of {{PublicKeyCredentialCreationOptions/hints}} and craft the user interface accordingly, as the user-agent sees fit.

1. Start |lifetimeTimer|.

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list -->
    <li id="CreateCred-async-loop">
        [=While=] |lifetimeTimer| has not expired, perform the following actions depending upon |lifetimeTimer|,
        and the state and response [=set/for each=] |authenticator| in |authenticators|:
        <dl class="switch">
            :   If |lifetimeTimer| expires,
            ::  [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
                and [=set/remove=] |authenticator| from |issuedRequests|.

            :   If the user exercises a user agent user-interface option to cancel the process,
            ::  [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
                and [=set/remove=] |authenticator| from |issuedRequests|. Throw a "{{NotAllowedError}}" {{DOMException}}.

            :   If <code>|options|.{{CredentialCreationOptions/signal}}</code> is present and [=AbortSignal/aborted=],
            ::  [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=]
                operation on |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|. Then throw the
                <code>|options|.{{CredentialCreationOptions/signal}}</code>'s [=AbortSignal/abort reason=].

            :   If an |authenticator| becomes available on this [=client device=],
            ::  Note:  This includes the case where an |authenticator| was available upon |lifetimeTimer| initiation.

                1. This |authenticator| is now the <dfn for="create">candidate authenticator</dfn>.

                1. If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}</code> is present:

                      1. If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/authenticatorAttachment}}</code> is
                        present and its value is not equal to |authenticator|'s [=authenticator attachment modality=], [=iteration/continue=].

                      1. If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{residentKey}}</code>

                          <dl class="switch">
                              :   is present and set to {{ResidentKeyRequirement/required}}
                              ::  If the |authenticator| is not capable of storing a [=client-side discoverable public key credential
                                  source=], [=iteration/continue=].

                              :   is present and set to {{ResidentKeyRequirement/preferred}} or {{ResidentKeyRequirement/discouraged}}
                              ::  No effect.

                              :   is not present
                              ::  if <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{requireResidentKey}}</code>
                                  is set to [TRUE] and the |authenticator| is not capable of storing a [=client-side discoverable public
                                  key credential source=], [=iteration/continue=].
                          </dl>

                      1. If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/userVerification}}</code> is
                        set to {{UserVerificationRequirement/required}} and the |authenticator| is not capable of performing [=user
                        verification=], [=iteration/continue=].

                1. Let |requireResidentKey| be the <dfn>effective resident key requirement for credential creation</dfn>, a Boolean value, as follows:

                    If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{residentKey}}</code>

                        <dl class="switch">

                            :   is present and set to {{ResidentKeyRequirement/required}}
                            ::  Let |requireResidentKey| be [TRUE].

                            :   is present and set to {{ResidentKeyRequirement/preferred}}
                            ::  If the |authenticator|

                                <dl class="switch">
                                    :   is capable of [=client-side credential storage modality=]
                                    ::  Let |requireResidentKey| be [TRUE].

                                    :   is not capable of [=client-side credential storage modality=], or if the [=client=] cannot determine authenticator capability,
                                    ::  Let |requireResidentKey| be [FALSE].
                                </dl>

                            :   is present and set to {{ResidentKeyRequirement/discouraged}}
                            ::  Let |requireResidentKey| be [FALSE].

                            :   is not present
                            ::  Let |requireResidentKey| be the value of <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{requireResidentKey}}</code>.

                        </dl>

                1. Let |userVerification| be the <dfn>effective user verification requirement for credential creation</dfn>, a Boolean value,
                    as follows. If
                    <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/userVerification}}</code>

                        <dl class="switch">

                            :   is set to {{UserVerificationRequirement/required}}
                            ::  1. If <code>|options|.{{CredentialCreationOptions/mediation}}</code> is set to {{CredentialMediationRequirement/conditional}}
                                    and [=user verification=] cannot be collected during the ceremony,
                                    throw a {{ConstraintError}} {{DOMException}}.
                                1. Let |userVerification| be [TRUE].

                            :   is set to {{UserVerificationRequirement/preferred}}
                            ::  If the |authenticator|

                                <dl class="switch">
                                    :   is capable of [=user verification=]
                                    ::  Let |userVerification| be [TRUE].

                                    :   is not capable of [=user verification=]
                                    ::  Let |userVerification| be [FALSE].
                                </dl>

                            :   is set to {{UserVerificationRequirement/discouraged}}
                            ::  Let |userVerification| be [FALSE].

                        </dl>

                1. Let |enterpriseAttestationPossible| be a Boolean value, as follows. If
                    <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/attestation}}</code>

                        <dl class="switch">

                            :   is set to {{AttestationConveyancePreference/enterprise}}
                            ::  Let |enterpriseAttestationPossible| be [TRUE] if the user agent wishes to support enterprise attestation for <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> (see [step 8](#CreateCred-DetermineRpId), above). Otherwise [FALSE].

                            :   otherwise
                            ::  Let |enterpriseAttestationPossible| be [FALSE].

                        </dl>

                1. Let |attestationFormats| be a list of strings, initialized to the value of <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/attestationFormats}}</code>.

                1. If <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/attestation}}</code>

                        <dl class="switch">

                            :   is set to {{AttestationConveyancePreference/none}}
                            ::  Set |attestationFormats| be the single-element list containing the string &ldquo;none&rdquo;

                        </dl>

                1. Let |excludeCredentialDescriptorList| be a new [=list=].

                1. [=list/For each=] credential descriptor |C| in <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/excludeCredentials}}</code>:
                    1. If <code>|C|.{{PublicKeyCredentialDescriptor/transports}}</code> [=list/is not empty=], and |authenticator| is connected over a transport not
                        mentioned in <code>|C|.{{PublicKeyCredentialDescriptor/transports}}</code>, the client MAY [=continue=].

                        Note: If the client chooses to [=continue=], this could result in
                        inadvertently registering multiple credentials [=bound credential|bound to=] the same [=authenticator=]
                        if the transport hints in <code>|C|.{{PublicKeyCredentialDescriptor/transports}}</code> are not accurate.
                        For example, stored transport hints could become inaccurate
                        as a result of software upgrades adding new connectivity options.

                    1. Otherwise, [=list/Append=] |C| to |excludeCredentialDescriptorList|.

                <!-- Note: this next step is actually a step on the same level as the above, but bikeshed wanted it indented this much
                in order to render it as a numbered step. If outdented, it (today) is rendered either as a bullet in the midst
                of a numbered list or is mis-numbered -->
                    <li id='CreateCred-InvokeAuthnrMakeCred'>
                        <!-- @@EDITOR-ANCHOR-01: KEEP THIS LIST SYNC'D WITH OTHER LOCATIONS WITH THIS TAG -->
                        Invoke the [=authenticatorMakeCredential=] operation on |authenticator| with
                            |clientDataHash|,
                            <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/rp}}</code>,
                            <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/user}}</code>,
                            |requireResidentKey|,
                            |userVerification|,
                            |credTypesAndPubKeyAlgs|,
                            |excludeCredentialDescriptorList|,
                            |enterpriseAttestationPossible|,
                            |attestationFormats|,
                            and |authenticatorExtensions| as parameters.
                    </li>

                1. [=set/Append=] |authenticator| to |issuedRequests|.

            :   If an |authenticator| ceases to be available on this [=client device=],
            ::  [=set/Remove=] |authenticator| from |issuedRequests|.

            :   If any |authenticator| returns a status indicating that the user cancelled the operation,
            ::  1. [=set/Remove=] |authenticator| from |issuedRequests|.
                1. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on
                    |authenticator| and [=set/remove=] it from |issuedRequests|.

                    Note: [=Authenticators=] may return an indication of "the user cancelled the entire operation".
                    How a user agent manifests this state to users is unspecified.

            :   If any |authenticator| returns an error status equivalent to "{{InvalidStateError}}",
            ::  1. [=set/Remove=] |authenticator| from |issuedRequests|.
                1. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on
                    |authenticator| and [=set/remove=] it from |issuedRequests|.
                1. Throw an "{{InvalidStateError}}" {{DOMException}}.

                Note: This error status is handled separately because the |authenticator| returns it only if
                |excludeCredentialDescriptorList| identifies a credential [=bound credential|bound=] to the |authenticator| and the user has [=user
                consent|consented=] to the operation. Given this explicit consent, it is acceptable for this case to be
                distinguishable to the [=[RP]=].

            :   If any |authenticator| returns an error status not equivalent to "{{InvalidStateError}}",
            ::  [=set/Remove=] |authenticator| from |issuedRequests|.

                Note: This case does not imply [=user consent=] for the operation, so details about the error are hidden from the
                [=[RP]=] in order to prevent leak of potentially identifying information. See [[#sctn-make-credential-privacy]] for
                details.

            :   If any |authenticator| indicates success,
            ::  1.  [=set/Remove=] |authenticator| from |issuedRequests|. This authenticator is now the <dfn for="create">selected authenticator</dfn>.

                1.  Let |credentialCreationData| be a [=struct=] whose [=struct/items=] are:

                    :   <code><dfn for="credentialCreationData">attestationObjectResult</dfn></code>
                    ::  whose value is the bytes returned from the successful [=authenticatorMakeCredential=] operation.

                        Note: this value is <code>attObj</code>, as defined in [[#sctn-generating-an-attestation-object]].

                    :   <code><dfn for="credentialCreationData">clientDataJSONResult</dfn></code>
                    ::  whose value is the bytes of |clientDataJSON|.

                    :   <code><dfn for="credentialCreationData">attestationConveyancePreferenceOption</dfn></code>
                    ::  whose value is the value of |pkOptions|.{{PublicKeyCredentialCreationOptions/attestation}}.

                    :   <code><dfn for="credentialCreationData">clientExtensionResults</dfn></code>
                    ::  whose value is an {{AuthenticationExtensionsClientOutputs}} object containing [=extension identifier=] →
                        [=client extension output=] entries. The entries are created by running each extension's
                        [=client extension processing=] algorithm to create the [=client extension outputs=], for each
                        [=client extension=] in <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/extensions}}</code>.

                1.  Let |constructCredentialAlg| be an algorithm that takes a [=global object=]
                    |global|, and whose steps are:

                    1.  If <code>|credentialCreationData|.[=attestationConveyancePreferenceOption=]</code>'s value is
                        <dl class="switch">
                            :   {{AttestationConveyancePreference/none}}
                            ::  Replace potentially uniquely identifying information with non-identifying versions of the
                                same:
                                  1. If the [=authData/attestedCredentialData/aaguid=] in the [=attested credential data=] is 16 zero bytes, <code>|credentialCreationData|.[=attestationObjectResult=].fmt</code> is "packed", and "x5c" is absent from <code>|credentialCreationData|.[=attestationObjectResult=]</code>, then [=self attestation=] is being used and no further action is needed.
                                  1. Otherwise:
                                      1. Set the value of <code>|credentialCreationData|.[=attestationObjectResult=].fmt</code> to "none", and set the value of <code>|credentialCreationData|.[=attestationObjectResult=].attStmt</code> to be an empty [=CBOR=] map. (See [[#sctn-none-attestation]] and [[#sctn-generating-an-attestation-object]]).

                            :   {{AttestationConveyancePreference/indirect}}
                            ::  The client MAY replace the [=authData/attestedCredentialData/aaguid=] and [=attestation statement=] with a more privacy-friendly
                                and/or more easily verifiable version of the same data (for example, by employing an [=Anonymization CA=]).

                            :   {{AttestationConveyancePreference/direct}} or {{AttestationConveyancePreference/enterprise}}
                            ::  Convey the [=authenticator=]'s [=/AAGUID=] and [=attestation statement=], unaltered, to the [=[RP]=].
                        </dl>

                    1.  Let |attestationObject| be a new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the
                        bytes of <code>|credentialCreationData|.[=attestationObjectResult=]</code>'s value.

                    1.  Let |id| be <code>|attestationObject|.authData.[=attestedCredentialData=].[=credentialId=]</code>.

                    1.  Let |pubKeyCred| be a new {{PublicKeyCredential}} object associated with |global| whose fields are:

                        :   {{PublicKeyCredential/[[identifier]]}}
                        ::  |id|

                        :   {{PublicKeyCredential/authenticatorAttachment}}
                        ::  The {{AuthenticatorAttachment}} value matching the current [=authenticator attachment modality=] of |authenticator|.

                        :   {{PublicKeyCredential/response}}
                        ::  A new {{AuthenticatorAttestationResponse}} object associated with |global| whose fields are:

                            :   {{AuthenticatorResponse/clientDataJSON}}
                            ::  A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of
                                <code>|credentialCreationData|.[=credentialCreationData/clientDataJSONResult=]</code>.

                            :   {{AuthenticatorAttestationResponse/attestationObject}}
                            ::  |attestationObject|

                            :   {{AuthenticatorAttestationResponse/[[transports]]}}
                            ::  A sequence of zero or more unique {{DOMString}}s, in lexicographical order, that the |authenticator| is believed to support. The values SHOULD be members of {{AuthenticatorTransport}}, but [=client platforms=] MUST ignore unknown values.

                                If a user agent does not wish to divulge this information it MAY substitute an arbitrary sequence designed to preserve privacy. This sequence MUST still be valid, i.e. lexicographically sorted and free of duplicates. For example, it may use the empty sequence. Either way, in this case the user agent takes the risk that [=[RP]=] behavior may be suboptimal.

                                If the user agent does not have any transport information, it SHOULD set this field to the empty sequence.

                                Note: How user agents discover transports supported by a given [=authenticator=] is outside the scope of this specification, but may include information from an [=attestation certificate=] (for example [[FIDO-Transports-Ext]]), metadata communicated in an [=authenticator=] protocol such as CTAP2, or special-case knowledge about a [=platform authenticator=].

                        :   {{PublicKeyCredential/[[clientExtensionsResults]]}}
                        ::  A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of
                            <code>|credentialCreationData|.[=credentialCreationData/clientExtensionResults=]</code>.

                    1.  Return |pubKeyCred|.

                1. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on
                    |authenticator| and [=set/remove=] it from |issuedRequests|.

                1. Return |constructCredentialAlg| and terminate this algorithm.

        </dl>
    </li>

1. Throw a "{{NotAllowedError}}" {{DOMException}}.

During the above process, the user agent SHOULD show some UI to the user to guide them in the process of selecting and
authorizing an authenticator. When <code>|options|.{{CredentialCreationOptions/mediation}}</code> is set to {{CredentialMediationRequirement/conditional}}, prominent modal UI should <i>not</i> be shown <i>unless</i> credential creation was previously consented to via means determined by the user agent.
</div>

#### Create Request Exceptions #### {#sctn-create-request-exceptions}

[INFORMATIVE]

[=[WRPS]=] can encounter a number of exceptions from a call to {{CredentialsContainer/create()|navigator.credentials.create()}}.
Some exceptions can have multiple reasons for why they happened,
requiring the [=[WRPS]=] to infer the actual reason based on their use of WebAuthn.

Note: Exceptions that can be raised during processing of any [=WebAuthn Extensions=],
including ones defined outside of this specification,
are not listed here.

The following {{DOMException}} exceptions can be raised:

<dl>
    :   {{AbortError}}
    ::  The ceremony was cancelled by an {{AbortController}}.
        See [[#sctn-abortoperation]] and [[#sctn-sample-aborting]].

    :   {{ConstraintError}}
    ::  Either {{residentKey}} was set to {{ResidentKeyRequirement/required}} and no available authenticator supported resident keys,
        or {{AuthenticatorSelectionCriteria/userVerification}} was set to {{UserVerificationRequirement/required}} and no available authenticator could perform [=user verification=].

    :   {{InvalidStateError}}
    ::  The authenticator used in the ceremony recognized an entry in {{PublicKeyCredentialCreationOptions/excludeCredentials}}
        after the user [=user consent|consented=] to registering a credential.

    :   {{NotSupportedError}}
    ::  No entry in {{PublicKeyCredentialCreationOptions/pubKeyCredParams}} had a {{PublicKeyCredentialDescriptor/type}} property of {{PublicKeyCredentialType/public-key}},
        or the [=authenticator=] did not support any of the signature algorithms specified in {{PublicKeyCredentialCreationOptions/pubKeyCredParams}}.

    :   {{SecurityError}}
    ::  The [=effective domain=] was not a [=valid domain=],
        or <code>{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> was not equal to or a registrable domain suffix of the [=effective domain=].
        In the latter case,
        the [=client=] does not support [[#sctn-related-origins|related origin requests]]
        or the [$related origins validation procedure$] failed.

    :   {{NotAllowedError}}
    ::  A catch-all error covering a wide range of possible reasons,
        including common ones like the user canceling out of the ceremony.
        Some of these causes are documented throughout this spec,
        while others are client-specific.

</dl>

The following [=simple exceptions=] can be raised:

<dl>

    :   {{TypeError}}
    ::  The <code>|options|</code> argument was not a valid <code>[[#sctn-credentialcreationoptions-extension|CredentialCreationOptions]]</code> value,
        or the value of <code>{{PublicKeyCredentialCreationOptions/user}}.{{PublicKeyCredentialUserEntity/id}}</code> was empty or was longer than 64 bytes.

</dl>

### Use an Existing Credential to Make an Assertion ### {#sctn-getAssertion}

[=[WRPS]=] call <code><a idl for="CredentialsContainer" lt="get()">navigator.credentials.get({publicKey:..., ...})</a></code> to
discover and use an existing [=public key credential=], with the [=user consent|user's consent=]. [=[RP]=] script optionally specifies some criteria
to indicate what [=public key credential sources=] are acceptable to it. The [=client platform=] locates [=public key credential sources=]
matching the specified criteria, and guides the user to pick one that the script will be allowed to use. The user may choose to
decline the entire interaction even if a [=public key credential source=] is present, for example to maintain privacy. If the user picks a
[=public key credential source=], the user agent then uses
[[#sctn-op-get-assertion]] to sign a [=[RP]=]-provided challenge and other collected data into an [=authentication assertion=], which is used as a
[=credential=].

The {{CredentialsContainer/get()|navigator.credentials.get()}} implementation [[!CREDENTIAL-MANAGEMENT-1]] calls
<code>PublicKeyCredential.{{Credential/[[CollectFromCredentialStore]]()}}</code> to collect any [=credentials=] that
should be available without [=user mediation=] (roughly, this specification's [=authorization gesture=]), and if it does not find
exactly one of those, it then calls <code>PublicKeyCredential.{{PublicKeyCredential/[DISCOVER-METHOD]}}</code> to have
the user select a [=public key credential source=].

Since this specification requires an [=authorization gesture=] to create any [=assertions=],
{{PublicKeyCredential}} inherits the default behavior of
{{Credential/[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)}}, of returning an empty set.
{{PublicKeyCredential}}'s implementation of {{PublicKeyCredential/[DISCOVER-METHOD]}} is specified in the next section.

In general, the user agent SHOULD show some UI to the user to guide them in selecting and authorizing an authenticator with which
to complete the operation. By setting <code>|options|.{{CredentialRequestOptions/mediation}}</code> to {{CredentialMediationRequirement/conditional}}, [=[RPS]=] can indicate that a prominent modal UI should <i>not</i> be shown <i>unless</i> credentials are discovered.
The [=[RP]=] SHOULD first use {{PublicKeyCredential/isConditionalMediationAvailable()}}
or {{PublicKeyCredential/getClientCapabilities()}}
to check that the [=client=] supports the {{ClientCapability/conditionalGet}} capability
in order to prevent a user-visible error in case this feature is not available.

Any
{{CredentialsContainer/get()|navigator.credentials.get()}} operation can be aborted by leveraging the {{AbortController}};
see [[dom#abortcontroller-api-integration]] for detailed instructions.

#### PublicKeyCredential's <code><dfn for="PublicKeyCredential" method>[DISCOVER-METHOD-DEF]</dfn></code> Internal Method #### {#sctn-discover-from-external-source}

<div link-for-hint="PublicKeyCredential/[DISCOVER-METHOD]">

This [=internal method=] accepts three arguments:

<dl dfn-type="argument" dfn-for="PublicKeyCredential/[DISCOVER-METHOD]">

    :   <dfn>origin</dfn>
    ::  This argument is the [=relevant settings object=]'s [=environment settings object/origin=], as determined by the
        calling {{CredentialsContainer/get()}} implementation, i.e., {{CredentialsContainer}}'s <a abstract-op>Request a `Credential`</a> abstract operation.

    :   <dfn>options</dfn>
    ::  This argument is a {{CredentialRequestOptions}} object whose
        <code>|options|.{{CredentialRequestOptions/publicKey}}</code> member contains a {{PublicKeyCredentialRequestOptions}}
        object specifying the desired attributes of the [=public key credential=] to discover.

    :   <dfn>sameOriginWithAncestors</dfn>
    ::  This argument is a Boolean value which is [TRUE] if and only if the caller's [=environment settings object=] is
        [=same-origin with its ancestors=]. It is [FALSE] if caller is cross-origin.

        Note: Invocation of this [=internal method=] indicates that it was allowed by
        [=permissions policy=], which is evaluated at the [[!CREDENTIAL-MANAGEMENT-1]] level.
        See [[#sctn-permissions-policy]].
</dl>

Note: <strong>This algorithm is synchronous:</strong> the {{Promise}} resolution/rejection is handled by
{{CredentialsContainer/get()|navigator.credentials.get()}}.

All {{BufferSource}} objects used in this algorithm MUST be snapshotted when the algorithm begins, to
avoid potential synchronization issues. Implementations SHOULD [=get a copy of the bytes held
by the buffer source=] and use that copy for relevant portions of the algorithm.

When this method is invoked, the user agent MUST execute the following algorithm:

1. Assert: <code>|options|.{{CredentialRequestOptions/publicKey}}</code> is present.

1. Let |pkOptions| be the value of <code>|options|.{{CredentialRequestOptions/publicKey}}</code>.

1. If <code>|options|.{{CredentialRequestOptions/mediation}}</code> is present with the value
    {{CredentialMediationRequirement/conditional}}:

    1. Let |credentialIdFilter| be the value of <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code>.

    1. Set <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code> to [=list/empty=].

        Note: This prevents [=non-discoverable credentials=] from being used during {{CredentialMediationRequirement/conditional}} requests.

    1. Set a timer |lifetimeTimer| to a value of infinity.

        Note: |lifetimeTimer| is set to a value of infinity so that the user has the entire lifetime of
        the [=Document=] to interact with any <{input}> form control tagged with a `"webauthn"` [=autofill detail token=]. For example, upon the user clicking in such an input field, the user agent can render a list of discovered credentials for the user to select from, and perhaps also give the user the option to "try another way".

1. Else:

    1. Let |credentialIdFilter| be an [=list/empty=] [=list=].

    1. If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/timeout}}</code> is present, check if its value lies
        within a reasonable range as defined by the [=client=] and if not, correct it to the closest value lying within that range.
        Set a timer |lifetimeTimer| to this adjusted value. If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/timeout}}</code>
        is not present, then set |lifetimeTimer| to a [=client=]-specific default.

            See the [=recommended range and default for a WebAuthn ceremony timeout=]
            for guidance on deciding a reasonable range and default for <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/timeout}}</code>.

            The user agent SHOULD take cognitive guidelines into considerations regarding timeout for users with special needs.

1. Let |callerOrigin| be {{PublicKeyCredential/[DISCOVER-METHOD]/origin}}. If |callerOrigin| is
    an [=opaque origin=], throw a "{{NotAllowedError}}" {{DOMException}}.

1. Let |effectiveDomain| be the |callerOrigin|'s [=effective domain=].
    If [=effective domain=] is not a [=valid domain=], then throw a
    "{{SecurityError}}" {{DOMException}}.

    Note: An [=effective domain=] may resolve to a [=host=], which can be represented in various manners,
        such as [=domain=], [=ipv4 address=], [=ipv6 address=], [=opaque host=], or [=empty host=].
        Only the [=domain=] format of [=host=] is allowed here. This is for simplification and also is
        in recognition of various issues with using direct IP address identification in concert with
        PKI-based security.

        <li id='GetAssn-DetermineRpId'>
            If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code>
                <dl class="switch">

                    :   is present
                    ::  If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code> [=is not a
                        registrable domain suffix of and is not equal to=] |effectiveDomain|, and if the client

                        <dl class="switch">
                            :   supports [[#sctn-related-origins|related origin requests]]
                            ::  1. Let |rpIdRequested| be the value of <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code>

                                1. Run the [$related origins validation procedure$] with arguments |callerOrigin| and |rpIdRequested|.
                                    If the result is [FALSE], throw a "{{SecurityError}}" {{DOMException}}.

                            :   does not support [[#sctn-related-origins|related origin requests]]
                            ::  throw a "{{SecurityError}}" {{DOMException}}.
                        </dl>

                    :   is not present
                    ::  Set <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code> to |effectiveDomain|.
                </dl>

            Note: |rpId| represents the caller's [=RP ID=]. The [=RP ID=] defaults to being the caller's [=environment
            settings object/origin=]'s [=effective domain=] unless the caller has explicitly set
            <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/rpId}}</code> when calling {{CredentialsContainer/get()}}.
        </li>

1. Let |clientExtensions| be a new [=map=] and let |authenticatorExtensions| be a new [=map=].

1. If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/extensions}}</code> is present, then [=map/for each=]
    |extensionId| → |clientExtensionInput| of <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/extensions}}</code>:
    1. If |extensionId| is not supported by this [=client platform=] or is not an [=authentication extension=], then [=continue=].

    1. [=map/Set=] |clientExtensions|[|extensionId|] to |clientExtensionInput|.

    1. If |extensionId| is not an [=authenticator extension=], then [=continue=].

    1. Let |authenticatorExtensionInput| be the ([=CBOR=]) result of running |extensionId|'s [=client extension processing=]
        algorithm on |clientExtensionInput|. If the algorithm returned an error, [=continue=].

    1. [=map/Set=] |authenticatorExtensions|[|extensionId|] to the [=base64url encoding=] of |authenticatorExtensionInput|.

1. Let |collectedClientData| be a new {{CollectedClientData}} instance whose fields are:
    : {{CollectedClientData/type}}
    :: The string "webauthn.get".
    : {{CollectedClientData/challenge}}
    :: The [=base64url encoding=] of |pkOptions|.{{PublicKeyCredentialRequestOptions/challenge}}
    : {{CollectedClientData/origin}}
    :: The [=ascii serialization of an origin|serialization of=] |callerOrigin|.
    : {{CollectedClientData/crossOrigin}}
    :: The inverse of the value of the
        {{PublicKeyCredential/[DISCOVER-METHOD]/sameOriginWithAncestors}}
        argument passed to this [=internal method=].
    : {{CollectedClientData/topOrigin}}
    :: The [=ascii serialization of an origin|serialization of=] |callerOrigin|'s [=top-level origin=] if
        the {{PublicKeyCredential/[DISCOVER-METHOD]/sameOriginWithAncestors}}
        argument passed to this [=internal method=] is [FALSE], else `undefined`.

1. Let |clientDataJSON| be the [=JSON-compatible serialization of client data=] constructed from |collectedClientData|.

1. Let |clientDataHash| be the [=hash of the serialized client data=] represented by |clientDataJSON|.

1. If <code>|options|.{{CredentialRequestOptions/signal}}</code> is present and [=AbortSignal/aborted=], throw
    the <code>|options|.{{CredentialRequestOptions/signal}}</code>'s [=AbortSignal/abort reason=].

1. Let |issuedRequests| be a new [=ordered set=].

1. Let |savedCredentialIds| be a new [=map=].

1. Let |authenticators| represent a value which at any given instant is a [=set=] of [=client platform=]-specific handles, where each
    [=set/item=] identifies an [=authenticator=] presently available on this [=client platform=] at that instant.

    Note: What qualifies an [=authenticator=] as "available" is intentionally unspecified; this is meant to represent how
    [=authenticators=] can be <a href="https://en.wikipedia.org/w/index.php?title=Hot_plug">hot-plugged</a> into (e.g., via USB)
    or discovered (e.g., via NFC or Bluetooth) by the [=client=] by various mechanisms, or permanently built into the [=client=].

1. Let |silentlyDiscoveredCredentials| be a new [=map=] whose [=map/entry|entries=] are of the form: [=DiscoverableCredentialMetadata=] → [=authenticator=].

1. Consider the value of {{PublicKeyCredentialRequestOptions/hints}} and craft the user interface accordingly, as the user-agent sees fit.

1. Start |lifetimeTimer|.

1. [=While=] |lifetimeTimer| has not expired, perform the following actions depending upon |lifetimeTimer|,
    and the state and response [=set/for each=] |authenticator| in |authenticators|:

    <dl class="switch">

        :   If |lifetimeTimer| expires,
        ::  [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on
            |authenticator| and [=set/remove=] |authenticator| from |issuedRequests|.

        :   If the user exercises a user agent user-interface option to cancel the process,
        ::  [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
            and [=set/remove=] |authenticator| from |issuedRequests|. Throw a "{{NotAllowedError}}" {{DOMException}}.

        :   If <code>|options|.{{CredentialRequestOptions/signal}}</code> is present and [=AbortSignal/aborted=],
        ::  [=set/For each=] |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation on |authenticator|
            and [=set/remove=] |authenticator| from |issuedRequests|. Then
            throw the <code>|options|.{{CredentialRequestOptions/signal}}</code>'s [=AbortSignal/abort reason=].

            <!-- this needs to be indented 2 more levels to get it to render properly -->
                <dt id="GetAssn-ConditionalMediation-Interact-FormControl">
                  If <code>|options|.{{CredentialRequestOptions/mediation}}</code> is {{CredentialMediationRequirement/conditional}}
                  and the user interacts with an <{input}> or <{textarea}> form control with an <{input/autocomplete}> attribute whose
                  [=non-autofill credential type=] is `"webauthn"`,
                </dt>
        ::  <div class="note">
                <!-- This is a consequence of the autofill processing model, not a requirement imposed by this spec -->
                <span class="marker">Note:</span>
                The `"webauthn"` [=autofill detail token=] must appear immediately after the last [=autofill detail token=]
                of type "Normal" or "Contact". For example:

                - `"username webauthn"`
                - `"current-password webauthn"`
            </div>

            1. If |silentlyDiscoveredCredentials| is not [=list/empty=]:

                1. Prompt the user to optionally select a [=DiscoverableCredentialMetadata=] from |silentlyDiscoveredCredentials|.
                    The prompt SHOULD display values from the [=DiscoverableCredentialMetadata/otherUI=] of each [=DiscoverableCredentialMetadata=],
                    such as {{PublicKeyCredentialEntity/name}} and {{PublicKeyCredentialUserEntity/displayName}}.

                    Let |credentialMetadata| be the [=DiscoverableCredentialMetadata=] chosen by the user, if any.

                1. If the user selects a |credentialMetadata|,

                    1. Let |publicKeyOptions| be a temporary copy of |pkOptions|.

                    1. Let |authenticator| be the value of |silentlyDiscoveredCredentials|[|credentialMetadata|].

                    1. Set <code>|publicKeyOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code> to be a [=list=] containing a
                        single {{PublicKeyCredentialDescriptor}} [=list/item=] whose {{PublicKeyCredentialDescriptor/id}}'s value is set to
                        |credentialMetadata|'s [=DiscoverableCredentialMetadata/id=]'s value and whose {{PublicKeyCredentialDescriptor/type}}
                        value is set to |credentialMetadata|'s [=DiscoverableCredentialMetadata/type=].

                    1. Execute the [=issuing a credential request to an authenticator=] algorithm with |authenticator|, |savedCredentialIds|,
                        |publicKeyOptions|, |rpId|, |clientDataHash|, and |authenticatorExtensions|.

                        If this returns [FALSE], [=continue=].

                    1. [=set/Append=] |authenticator| to |issuedRequests|.

        :   If <code>|options|.{{CredentialRequestOptions/mediation}}</code> is not {{CredentialMediationRequirement/conditional}},
            |issuedRequests| is empty, <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code> is not empty,
            and no |authenticator| will become available for any [=public key credentials=] therein,
        ::  Indicate to the user that no eligible credential could be found. When the user acknowledges the dialog, throw a "{{NotAllowedError}}" {{DOMException}}.

            Note: One way a [=client platform=] can determine that no |authenticator| will become available is by examining the <code>{{PublicKeyCredentialDescriptor/transports}}</code> members of the present <code>{{PublicKeyCredentialDescriptor}}</code> [=list/items=] of <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code>, if any. For example, if all <code>{{PublicKeyCredentialDescriptor}}</code> [=list/items=] list only <code>{{AuthenticatorTransport/internal}}</code>, but all [=platform authenticator|platform=] |authenticator|s have been tried, then there is no possibility of satisfying the request. Alternatively, all <code>{{PublicKeyCredentialDescriptor}}</code> [=list/items=] may list <code>{{PublicKeyCredentialDescriptor/transports}}</code> that the [=client platform=] does not support.

        :   If an |authenticator| becomes available on this [=client device=],
        ::  Note:  This includes the case where an |authenticator| was available upon |lifetimeTimer| initiation.

            1. If <code>|options|.{{CredentialRequestOptions/mediation}}</code> is {{CredentialMediationRequirement/conditional}}
                and the |authenticator| supports the [=silentCredentialDiscovery=] operation:

                1. Let |collectedDiscoveredCredentialMetadata| be the result of invoking the [=silentCredentialDiscovery=] operation on |authenticator| with |rpId| as parameter.

                1. [=list/For each=] |credentialMetadata| of |collectedDiscoveredCredentialMetadata|:

                    1. If |credentialIdFilter| [=list/is empty=] or |credentialIdFilter| contains an item whose
                        {{PublicKeyCredentialDescriptor/id}}'s value is set to |credentialMetadata|'s [=DiscoverableCredentialMetadata/id=],
                        [=map/set=] |silentlyDiscoveredCredentials|[|credentialMetadata|] to |authenticator|.

                           Note: A request will be issued to this authenticator upon user selection of a credential via
                           interaction with a particular UI context
                           (see [here](#GetAssn-ConditionalMediation-Interact-FormControl) for details).

            1. Else:

                1. Execute the [=issuing a credential request to an authenticator=] algorithm with |authenticator|, |savedCredentialIds|,
                    |pkOptions|, |rpId|, |clientDataHash|, and |authenticatorExtensions|.

                    If this returns [FALSE], [=continue=].

                    Note: This branch is taken if <code>|options|.{{CredentialRequestOptions/mediation}}</code> is {{CredentialMediationRequirement/conditional}}
                    and the |authenticator| does not support the [=silentCredentialDiscovery=] operation to allow use of such authenticators during a
                    {{CredentialMediationRequirement/conditional}} [=user mediation=] request.

                1. [=set/Append=] |authenticator| to |issuedRequests|.

        :   If an |authenticator| ceases to be available on this [=client device=],
        ::  [=set/Remove=] |authenticator| from |issuedRequests|.

        :   If any |authenticator| returns a status indicating that the user cancelled the operation,
        ::  1. [=set/Remove=] |authenticator| from |issuedRequests|.
            1. [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation
                on |authenticator| and [=set/remove=] it from |issuedRequests|.

                Note: [=Authenticators=] may return an indication of "the user cancelled the entire operation".
                How a user agent manifests this state to users is unspecified.

        :   If any |authenticator| returns an error status,
        ::  [=set/Remove=] |authenticator| from |issuedRequests|.

        :   If any |authenticator| indicates success,
        ::  1.  [=set/Remove=] |authenticator| from |issuedRequests|.

            1.  <span id="assertionCreationDataCreation"></span>
                Let <var ignore>assertionCreationData</var> be a [=struct=] whose [=struct/items=] are:

                :   <code><dfn for="assertionCreationData">credentialIdResult</dfn></code>
                ::  If <code>|savedCredentialIds|[|authenticator|]</code> exists, set the value of [=credentialIdResult=] to be
                    the bytes of <code>|savedCredentialIds|[|authenticator|]</code>. Otherwise, set the value of
                    [=credentialIdResult=] to be the bytes of the [=credential ID=] returned from the successful
                    [=authenticatorGetAssertion=] operation, as defined in [[#sctn-op-get-assertion]].

                :   <code><dfn for="assertionCreationData">clientDataJSONResult</dfn></code>
                ::  whose value is the bytes of |clientDataJSON|.

                :   <code><dfn for="assertionCreationData">authenticatorDataResult</dfn></code>
                ::  whose value is the bytes of the [=authenticator data=] returned by the [=authenticator=].

                :   <code><dfn for="assertionCreationData">signatureResult</dfn></code>
                ::  whose value is the bytes of the signature value returned by the [=authenticator=].

                :   <code><dfn for="assertionCreationData">userHandleResult</dfn></code>
                ::  If the [=authenticator=] returned a [=user handle=], set the value of [=userHandleResult=] to be the bytes of
                    the returned [=user handle=]. Otherwise, set the value of [=userHandleResult=] to null.

                :   <code><dfn for="assertionCreationData">clientExtensionResults</dfn></code>
                ::  whose value is an {{AuthenticationExtensionsClientOutputs}} object containing [=extension identifier=] →
                    [=client extension output=] entries. The entries are created by running each extension's
                    [=client extension processing=] algorithm to create the [=client extension outputs=], for each
                    [=client extension=] in <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/extensions}}</code>.

            1. If |credentialIdFilter| [=list/is not empty=] and |credentialIdFilter| does not contain an item whose
                {{PublicKeyCredentialDescriptor/id}}'s value is set to the value of [=credentialIdResult=], [=continue=].

            1. If |credentialIdFilter| [=list/is empty=] and [=userHandleResult=] is null, [=continue=].

            1. Let |settings| be the [=current settings object=]. Let |global| be |settings|’ [=global object=].

            1.  Let |pubKeyCred| be a new {{PublicKeyCredential}} object associated with |global| whose fields are:

                :   {{PublicKeyCredential/[[identifier]]}}
                ::  A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of
                    <code>|assertionCreationData|.[=credentialIdResult=]</code>.

                :   {{PublicKeyCredential/authenticatorAttachment}}
                ::  The {{AuthenticatorAttachment}} value matching the current [=authenticator attachment modality=] of |authenticator|.

                :   {{PublicKeyCredential/response}}
                ::  A new {{AuthenticatorAssertionResponse}} object associated with |global| whose fields are:

                    :   {{AuthenticatorResponse/clientDataJSON}}
                    ::  A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of
                        <code>|assertionCreationData|.[=assertionCreationData/clientDataJSONResult=]</code>.

                    :   {{AuthenticatorAssertionResponse/authenticatorData}}
                    ::  A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of
                        <code>|assertionCreationData|.[=assertionCreationData/authenticatorDataResult=]</code>.

                    :   {{AuthenticatorAssertionResponse/signature}}
                    ::  A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of
                        <code>|assertionCreationData|.[=assertionCreationData/signatureResult=]</code>.

                    :   {{AuthenticatorAssertionResponse/userHandle}}
                    ::  If <code>|assertionCreationData|.[=assertionCreationData/userHandleResult=]</code> is null, set this
                        field to null. Otherwise, set this field to a new {{ArrayBuffer}}, created using |global|'s
                        [=%ArrayBuffer%=], containing the bytes of
                        <code>|assertionCreationData|.[=assertionCreationData/userHandleResult=]</code>.

                :   {{PublicKeyCredential/[[clientExtensionsResults]]}}
                ::  A new {{ArrayBuffer}}, created using |global|'s [=%ArrayBuffer%=], containing the bytes of
                    <code>|assertionCreationData|.[=assertionCreationData/clientExtensionResults=]</code>.

            1.  [=set/For each=] remaining |authenticator| in |issuedRequests| invoke the [=authenticatorCancel=] operation
                on |authenticator| and [=set/remove=] it from |issuedRequests|.

            1.  Return |pubKeyCred| and terminate this algorithm.
    </dl>

1. Throw a "{{NotAllowedError}}" {{DOMException}}.

</div>

#### <dfn for="PublicKeyCredential" algorithm="Issuing a credential request to an authenticator">Issuing a Credential Request to an Authenticator</dfn> #### {#sctn-issuing-cred-request-to-authenticator}

This sub-algorithm of {{PublicKeyCredential/[DISCOVER-METHOD]}} encompasses the specific UI context-independent
steps necessary for requesting a [=credential=] from a given [=authenticator=], using given {{PublicKeyCredentialRequestOptions}}.
It is called by {{PublicKeyCredential/[DISCOVER-METHOD]}} from various points depending on which [=user mediation=]
the present [=authentication ceremony=] is subject to (e.g.: {{CredentialMediationRequirement/conditional}} mediation).

This algorithm accepts the following arguments:

<dl dfn-type="argument" dfn-for="Issuing a credential request to an authenticator">
    :   <dfn>authenticator</dfn>
    ::  A [=client platform=]-specific handle identifying an [=authenticator=] presently available on this [=client platform=].

    :   <dfn>savedCredentialIds</dfn>
    ::  A [=map=] containing [=authenticator=] → [=credential ID=]. This argument will be modified in this algorithm.

    :   <dfn>pkOptions</dfn>
    ::  This argument is a {{PublicKeyCredentialRequestOptions}} object specifying the desired attributes of the
        [=public key credential=] to discover.

    :   <dfn>rpId</dfn>
    ::  The request [=RP ID=].

    :   <dfn>clientDataHash</dfn>
    ::  The [=hash of the serialized client data=] represented by |clientDataJSON|.

    :   <dfn>authenticatorExtensions</dfn>
    ::  A [=map=] containing [=extension identifiers=] to the [=base64url encoding=] of the [=client extension processing=]
        output for [=authenticator extensions=].
</dl>

This algorithm returns [FALSE] if the [=client=] determines that the |authenticator| is not capable of handling the request, or [TRUE] if
the request was issued successfully.

The steps for [=issuing a credential request to an authenticator=] are as follows:

    1. If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/userVerification}}</code> is set to
        {{UserVerificationRequirement/required}} and the |authenticator| is not capable of performing [=user verification=],
        return [FALSE].

    1. Let |userVerification| be the <dfn>effective user verification requirement for assertion</dfn>, a Boolean value, as
        follows. If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/userVerification}}</code>

            <dl class="switch">

                :   is set to {{UserVerificationRequirement/required}}
                ::  Let |userVerification| be [TRUE].

                :   is set to {{UserVerificationRequirement/preferred}}
                ::  If the |authenticator|

                    <dl class="switch">
                        :   is capable of [=user verification=]
                        ::  Let |userVerification| be [TRUE].

                        :   is not capable of [=user verification=]
                        ::  Let |userVerification| be [FALSE].
                    </dl>

                :   is set to {{UserVerificationRequirement/discouraged}}
                ::  Let |userVerification| be [FALSE].

            </dl>

    1. <span id="allowCredentialDescriptorListCreation"></span>
        If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code>
        <dl class="switch">
            :   [=list/is not empty=]
            ::  1. Let |allowCredentialDescriptorList| be a new [=list=].

                1. Execute a [=client platform=]-specific procedure to determine which, if any, [=public key credentials=] described by
                    <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code> are [=bound credential|bound=] to this
                    |authenticator|, by matching with |rpId|,
                    <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}.{{PublicKeyCredentialDescriptor/id}}</code>,
                    and <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}.{{PublicKeyCredentialDescriptor/type}}</code>.
                    Set |allowCredentialDescriptorList| to this filtered list.

                1. If |allowCredentialDescriptorList| [=list/is empty=], return [FALSE].

                1. Let |distinctTransports| be a new [=ordered set=].

                1. If |allowCredentialDescriptorList| has exactly one value, set
                    <code>|savedCredentialIds|[|authenticator|]</code> to <code>|allowCredentialDescriptorList|[0].id</code>'s
                    value (see [here](#authenticatorGetAssertion-return-values) in [[#sctn-op-get-assertion]] for more information).

                1. [=list/For each=] credential descriptor |C| in |allowCredentialDescriptorList|,
                    [=set/append=] each value, if any, of <code>|C|.{{PublicKeyCredentialDescriptor/transports}}</code> to |distinctTransports|.

                    Note: This will aggregate only distinct values of {{PublicKeyCredentialDescriptor/transports}} (for this [=authenticator=]) in
                        |distinctTransports| due to the properties of [=ordered sets=].

                1. If |distinctTransports|
                    <dl class="switch">
                        :   [=list/is not empty=]
                        ::  The client selects one |transport| value from |distinctTransports|, possibly incorporating local
                            configuration knowledge of the appropriate transport to use with |authenticator| in making its
                            selection.

                            Then, using |transport|, invoke the [=authenticatorGetAssertion=] operation on
                            |authenticator|, with |rpId|, |clientDataHash|, |allowCredentialDescriptorList|,
                            |userVerification|,
                            and |authenticatorExtensions| as parameters.

                        :   [=list/is empty=]
                        ::  Using local configuration knowledge of the appropriate transport to use with |authenticator|,
                            invoke the [=authenticatorGetAssertion=] operation on |authenticator| with |rpId|,
                            |clientDataHash|, |allowCredentialDescriptorList|, |userVerification|,
                            and |authenticatorExtensions| as parameters.
                    </dl>

            :   [=list/is empty=]
            ::  Using local configuration knowledge of the appropriate transport to use with |authenticator|, invoke the
                [=authenticatorGetAssertion=] operation on |authenticator| with |rpId|, |clientDataHash|,
                |userVerification|,
                and |authenticatorExtensions| as parameters.

                Note: In this case, the [=[RP]=] did not supply a list of acceptable credential descriptors. Thus, the
                    authenticator is being asked to exercise any credential it may possess that is [=scoped=] to
                    the [=[RP]=], as identified by |rpId|.
        </dl>

    1. Return [TRUE].

#### Get Request Exceptions #### {#sctn-get-request-exceptions}

[INFORMATIVE]

[=[WRPS]=] can encounter a number of exceptions from a call to {{CredentialsContainer/get()|navigator.credentials.get()}}.
Some exceptions can have multiple reasons for why they happened,
requiring the [=[WRPS]=] to infer the actual reason based on their use of WebAuthn.

Note: Exceptions that can be raised during processing of any [=WebAuthn Extensions=],
including ones defined outside of this specification,
are not listed here.

The following {{DOMException}} exceptions can be raised:

<dl>
    :   {{AbortError}}
    ::  The ceremony was cancelled by an {{AbortController}}.
        See [[#sctn-abortoperation]] and [[#sctn-sample-aborting]].

    :   {{SecurityError}}
    ::  The [=effective domain=] was not a [=valid domain=],
        or <code>{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> was not equal to or a registrable domain suffix of the [=effective domain=].
        In the latter case,
        the [=client=] does not support [[#sctn-related-origins|related origin requests]]
        or the [$related origins validation procedure$] failed.

    :   {{NotAllowedError}}
    ::  A catch-all error covering a wide range of possible reasons,
        including common ones like the user canceling out of the ceremony.
        Some of these causes are documented throughout this spec,
        while others are client-specific.
</dl>

The following [=simple exceptions=] can be raised:

<dl>

    :   {{TypeError}}
    ::  The <code>|options|</code> argument was not a valid <code>[[#sctn-credentialrequestoptions-extension|CredentialRequestOptions]]</code> value.

</dl>

### Store an Existing Credential - PublicKeyCredential's `[[Store]](credential, sameOriginWithAncestors)` Internal Method ### {#sctn-storeCredential}

<div link-for-hint="PublicKeyCredential/[[Store]](credential, sameOriginWithAncestors)">

The {{Credential/[[Store]](credential, sameOriginWithAncestors)}} method is not supported
for Web Authentication's {{PublicKeyCredential}} type,
so its implementation of the <dfn for="PublicKeyCredential" method>\[[Store]](credential, sameOriginWithAncestors)</dfn>
[=internal method=] always throws an error.

Note: This algorithm is synchronous; the {{Promise}} resolution/rejection is handled by
{{CredentialsContainer/store()|navigator.credentials.store()}}.

This [=internal method=] accepts two arguments:

<dl dfn-type="argument" dfn-for="PublicKeyCredential/[[Store]](credential, sameOriginWithAncestors)">
    :   <dfn>credential</dfn>
    ::  This argument is a {{PublicKeyCredential}} object.

    :   <dfn>sameOriginWithAncestors</dfn>
    ::  This argument is a Boolean value which is [TRUE] if and only if the caller's [=environment settings object=] is
        [=same-origin with its ancestors=].
</dl>

When this method is invoked, the user agent MUST execute the following algorithm:

1. Throw a "{{NotSupportedError}}" {{DOMException}}.

</div>

### Availability of [=User-Verifying Platform Authenticator=] - PublicKeyCredential's `isUserVerifyingPlatformAuthenticatorAvailable()` Method ### {#sctn-isUserVerifyingPlatformAuthenticatorAvailable}

<div link-for-hint="WebAuthentication/isUserVerifyingPlatformAuthenticatorAvailable">

[=[WRPS]=] use this method to determine whether they can create a new credential using a [=user-verifying platform authenticator=].
Upon invocation, the [=client=] employs a [=client platform=]-specific procedure to discover available [=user-verifying platform authenticators=].
If any are discovered, the promise is resolved with the value of [TRUE].
Otherwise, the promise is resolved with the value of [FALSE].
Based on the result, the [=[RP]=] can take further actions to guide the user to create a credential.

This method has no arguments and returns a Boolean value.

<xmp class="idl">
    partial interface PublicKeyCredential {
        static Promise<boolean> isUserVerifyingPlatformAuthenticatorAvailable();
    };
</xmp>


</div>

### Availability of [=client=] capabilities - PublicKeyCredential's `getClientCapabilities()` Method ### {#sctn-getClientCapabilities}

<div link-for-hint="WebAuthentication/getClientCapabilities">

[=[WRPS]=] use this method to determine the availability of a limited set of [=WebAuthn Client|client=] capabilities to offer certain workflows and experiences to users. For example, an RP may offer a sign in button on clients where only {{AuthenticatorTransport/hybrid}} transport is available or where {{CredentialMediationRequirement/conditional}} mediation is unavailable (instead of showing a username field).

Upon invocation, the [=client=] employs a [=client platform=]-specific procedure to discover availability of these capabilities.

This method has no arguments and returns a record of capability keys to Boolean values.

<xmp class="idl">
    partial interface PublicKeyCredential {
        static Promise<PublicKeyCredentialClientCapabilities> getClientCapabilities();
    };

    typedef record<DOMString, boolean> PublicKeyCredentialClientCapabilities;
</xmp>

[=map/Keys=] in {{PublicKeyCredentialClientCapabilities}} MUST be sorted in ascending lexicographical order.
The set of [=map/keys=] SHOULD contain the set of [=enumeration values=] of {{ClientCapability}},
but the client MAY omit keys as it deems necessary; see [[#sctn-disclosing-client-capabilities]].

When the value for a given capability is [TRUE], the feature is known to be currently supported by the client.
When the value for a given capability is [FALSE], the feature is known to be not currently supported by the client.
When a capability does not [=map/exist=] as a key, the availability of the client feature is not known.

The set of [=map/keys=] SHOULD also contain a key for each [extension](#sctn-extensions) implemented by the client, where the key is formed by prefixing the string `extension:` to the [=extension identifier=]. The associated value for each implemented extension SHOULD be [TRUE]. If `getClientCapabilities()` is supported by a client, but an extension is not mapped to the value [TRUE], then a [=[RP]=] MAY assume that client processing steps for that extension will not be carried out by this client and that the extension MAY not be forwarded to the authenticator.

Note that even if an extension is mapped to [TRUE], the authenticator used for any given operation may not support that extension,
so [=[RPS]=] MUST NOT assume that the authenticator processing steps for that extension will be performed on that basis.

</div>

### Deserialize Registration ceremony options - PublicKeyCredential's `parseCreationOptionsFromJSON()` Method ### {#sctn-parseCreationOptionsFromJSON}

<div link-for-hint="WebAuthentication/parseCreationOptionsFromJSON">

[=[WRPS]=] use this method to convert [=JSON type=] representations of options for
{{CredentialsContainer/create()|navigator.credentials.create()}} into
{{PublicKeyCredentialCreationOptions}}.

Upon invocation, the [=client=] MUST convert the
{{PublicKeyCredential/parseCreationOptionsFromJSON(options)/options}} argument into a new,
identically-structured {{PublicKeyCredentialCreationOptions}} object, using [=base64url encoding=]
to decode any {{DOMString}} attributes in {{PublicKeyCredentialCreationOptionsJSON}} that correspond
to [=buffer source type=] attributes in {{PublicKeyCredentialCreationOptions}}. This conversion MUST
also apply to any [=client extension inputs=] processed by the [=client=].

{{AuthenticationExtensionsClientInputsJSON}} MAY include extensions registered in the IANA
"WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] but not defined in
[[#sctn-extensions]].

If the [=client=] encounters any issues parsing any of the [=JSON type=] representations then it
MUST throw an "{{EncodingError}}" {{DOMException}} with a description of the incompatible
value and terminate the operation.

<xmp class="idl">
    partial interface PublicKeyCredential {
        static PublicKeyCredentialCreationOptions parseCreationOptionsFromJSON(PublicKeyCredentialCreationOptionsJSON options);
    };

    dictionary PublicKeyCredentialCreationOptionsJSON {
        required PublicKeyCredentialRpEntity                    rp;
        required PublicKeyCredentialUserEntityJSON              user;
        required Base64URLString                                challenge;
        required sequence<PublicKeyCredentialParameters>        pubKeyCredParams;
        unsigned long                                           timeout;
        sequence<PublicKeyCredentialDescriptorJSON>             excludeCredentials = [];
        AuthenticatorSelectionCriteria                          authenticatorSelection;
        sequence<DOMString>                                     hints = [];
        DOMString                                               attestation = "none";
        sequence<DOMString>                                     attestationFormats = [];
        AuthenticationExtensionsClientInputsJSON                extensions;
    };

    dictionary PublicKeyCredentialUserEntityJSON {
        required Base64URLString        id;
        required DOMString              name;
        required DOMString              displayName;
    };

    dictionary PublicKeyCredentialDescriptorJSON {
        required DOMString              type;
        required Base64URLString        id;
        sequence<DOMString>             transports;
    };

    dictionary AuthenticationExtensionsClientInputsJSON {
    };
</xmp>

</div>

### Deserialize Authentication ceremony options - PublicKeyCredential's `parseRequestOptionsFromJSON()` Methods ### {#sctn-parseRequestOptionsFromJSON}

<div link-for-hint="WebAuthentication/parseRequestOptionsFromJSON">

[=[WRPS]=] use this method to convert [=JSON type=] representations of options for
{{CredentialsContainer/get()|navigator.credentials.get()}} into
{{PublicKeyCredentialRequestOptions}}.

Upon invocation, the [=client=] MUST convert the
{{PublicKeyCredential/parseRequestOptionsFromJSON(options)/options}} argument into a new,
identically-structured {{PublicKeyCredentialRequestOptions}} object, using [=base64url encoding=]
to decode any {{DOMString}} attributes in {{PublicKeyCredentialRequestOptionsJSON}} that correspond
to [=buffer source type=] attributes in {{PublicKeyCredentialRequestOptions}}. This conversion MUST
also apply to any [=client extension inputs=] processed by the [=client=].

{{AuthenticationExtensionsClientInputsJSON}} MAY include extensions registered in the IANA
"WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] but not defined in
[[#sctn-extensions]].

If the [=client=] encounters any issues parsing any of the [=JSON type=] representations then it
MUST throw an "{{EncodingError}}" {{DOMException}} with a description of the incompatible
value and terminate the operation.

<xmp class="idl">
    partial interface PublicKeyCredential {
        static PublicKeyCredentialRequestOptions parseRequestOptionsFromJSON(PublicKeyCredentialRequestOptionsJSON options);
    };

    dictionary PublicKeyCredentialRequestOptionsJSON {
        required Base64URLString                                challenge;
        unsigned long                                           timeout;
        DOMString                                               rpId;
        sequence<PublicKeyCredentialDescriptorJSON>             allowCredentials = [];
        DOMString                                               userVerification = "preferred";
        sequence<DOMString>                                     hints = [];
        AuthenticationExtensionsClientInputsJSON                extensions;
    };
</xmp>

</div>

### Signal Credential Changes to the Authenticator - PublicKeyCredential's [=signal methods=] ### {#sctn-signal-methods}

<xmp class="idl">
    partial interface PublicKeyCredential {
        static Promise<undefined> signalUnknownCredential(UnknownCredentialOptions options);
        static Promise<undefined> signalAllAcceptedCredentials(AllAcceptedCredentialsOptions options);
        static Promise<undefined> signalCurrentUserDetails(CurrentUserDetailsOptions options);
    };

    dictionary UnknownCredentialOptions {
        required DOMString                     rpId;
        required Base64URLString               credentialId;
    };

    dictionary AllAcceptedCredentialsOptions {
        required DOMString                     rpId;
        required Base64URLString               userId;
        required sequence<Base64URLString>     allAcceptedCredentialIds;
    };

    dictionary CurrentUserDetailsOptions {
        required DOMString                     rpId;
        required Base64URLString               userId;
        required DOMString                     name;
        required DOMString                     displayName;
    };
</xmp>

[=[WRPS]=] may use these <dfn>signal methods</dfn> to inform [=authenticators=]
of the state of [=public key credentials=], so that incorrect or revoked
credentials may be updated, removed, or hidden. [=Clients=] provide this
functionality opportunistically, since an authenticator may not support updating
its [=credentials map=] or may not be attached at the time the request is
made. Furthermore, in order to avoid revealing information about a user's
credentials without [=user consent=], [=signal methods=] do not indicate whether
the operation succeeded. A successfully resolved promise only means that the
<code>options</code> object was well formed.

Each [=signal method=] includes <dfn for="signal method">authenticator
actions</dfn>. [=Authenticators=] MAY choose to deviate in their [=signal
method/authenticator actions=] from the present specification, e.g. to ignore a
change they have a reasonable belief would be contrary to the user's wish, or to
ask the user before making some change. [=signal method/Authenticator actions=]
are thus provided as the recommended way to handle [=signal methods=].

In cases where an [=authenticator=] does not have the capability to process an
[=signal method/authenticator action=], [=clients=] MAY choose to use existing
infrastructure such as [[!FIDO-CTAP]]'s `authenticatorCredentialManagement`
command to achieve an equivalent effect.

Note: [=Signal methods=] intentionally avoid waiting for [=authenticators=] to
complete executing the [=signal method/authenticator actions=]. This measure protects users
from [=[WRPS]=] gaining information about availability of their credentials
without [=user consent=] based on the timing of the request.

#### <dfn abstract-op>Asynchronous RP ID validation algorithm</dfn> #### {#sctn-signal-methods-async-rp-id-validation}

The [$Asynchronous RP ID validation algorithm$] lets [=signal methods=] validate
[=RP IDs=] [=in parallel=]. The algorithm takes a {{DOMString}} |rpId| as input
and returns a promise that rejects if the validation fails. The steps are:

1. Let |effectiveDomain| be the [=relevant settings object=]'s [=environment
    settings object/origin=]'s [=effective domain=]. If |effectiveDomain| is
    not a [=valid domain=], then return [=a promise rejected with=]
    "{{SecurityError}}" {{DOMException}}.
1. If |rpId| [=is a registrable domain suffix of or is equal to=]
    |effectiveDomain|, return [=a promise resolved with=] undefined.
1. If the client does not support [[#sctn-related-origins|related origin
    requests]], return [=a promise rejected with=] a "{{SecurityError}}"
    {{DOMException}}.
1. Let |p| be [=a new promise=].
1. Execute the following steps [=in parallel=]:
    1. If the result of running the [$related origins validation procedure$]
        with arguments |callerOrigin| and |rpId| is [TRUE], then [=resolve=]
        |p|.
    1. Otherwise, [=reject=] |p| with a "{{SecurityError}}" {{DOMException}}.
1. Return |p|.

#### {{PublicKeyCredential/signalUnknownCredential(options)}} #### {#sctn-signalUnknownCredential}

The {{PublicKeyCredential/signalUnknownCredential(options)|signalUnknownCredential}} method signals that a [=credential id=] was not recognized by the [=[WRP]=],
e.g. because it was deleted by the user. Unlike {{PublicKeyCredential/signalAllAcceptedCredentials(options)}}, this
method does not require passing the entire list of accepted [=credential IDs=]
and the [=userHandle=], avoiding a privacy leak to an unauthenticated caller
(see [[#sctn-credential-id-privacy-leak]]).

Upon invocation of {{PublicKeyCredential/signalUnknownCredential(options)}},
the [=client=] executes these steps:

1. If the result of [=base64url encoding | base64url decoding=]
    <code>|options|.{{UnknownCredentialOptions/credentialId}}</code> is an
    error, then return [=a promise rejected with=] a {{TypeError}}.
1. Let |p| be the result of executing the [$Asynchronous RP ID validation
    algorithm$] with <code>|options|.{{UnknownCredentialOptions/rpId}}</code>.
1. [=Upon fulfillment=] of |p|, run the following steps [=in parallel=]:
    1. For every [=authenticator=] presently available on this [=client
        platform=], invoke the [=signal method/authenticator
        action/unknownCredentialId=] [=authenticator action=] with |options| as
        input.
1. Return |p|.

The <dfn for="signal method/authenticator action">unknownCredentialId</dfn>
[=signal method/authenticator action=] takes an {{UnknownCredentialOptions}}
|options| and is as follows:
1. [=map/For each=] [=public key credential source=] |credential| in the
    [=authenticator=]'s [=credential map=]:
    1. If the |credential|'s [=public key credential source/rpId=] equals
        <code>|options|.{{UnknownCredentialOptions/rpId}}</code> and the
        |credential|'s [=public key credential source/id=] equals the result of
        [=base64url encoding | base64url decoding=]
        <code>|options|.{{UnknownCredentialOptions/credentialId}}</code>,
        [=map/remove=] |credential| from the [=credentials map=] or employ an
        [=authenticator=]-specific procedure to hide it from future
        [=authentication ceremonies=].

<div class="example">

A user deletes a [=credential=] on a [=[WRP]=] provided UI. Later, when trying
to authenticate to the [=[WRP]=] with an [=list/empty=]
{{PublicKeyCredentialRequestOptions/allowCredentials}}, the [=authenticator=] UI
offers them the [=credential=] they previously deleted. The user selects that
[=credential=]. After rejecting the sign-in attempt, the [=[WRP]=] runs:

```javascript
PublicKeyCredential.signalUnknownCredential({
    rpId: "example.com",
    credentialId: "aabbcc"  // credential id the user just tried, base64url
});
```

The [=authenticator=] then deletes or hides the [=credential=] from future
[=authentication ceremonies=].

</div>

#### {{PublicKeyCredential/signalAllAcceptedCredentials(options)}} #### {#sctn-signalAllAcceptedCredentials}

Signals the complete list of [=credential ids=] for a given user. [=[WRPS]=]
SHOULD prefer this method over {{PublicKeyCredential/signalUnknownCredential()}}
when the user is authenticated and therefore there is no privacy leak risk (see
[[#sctn-credential-id-privacy-leak]]), since the list offers a full snapshot of
a user's [=public key credentials=] and might reflect changes that haven't yet
been reported to currently attached authenticators.

Upon invocation of
{{PublicKeyCredential/signalAllAcceptedCredentials(options)}}, the [=client=]
executes these steps:

1. If the result of [=base64url encoding | base64url decoding=]
    <code>|options|.{{AllAcceptedCredentialsOptions/userId}}</code> is an
    error, then return [=a promise rejected with=] a {{TypeError}}.
1. [=list/For each=] |credentialId| in
    <code>|options|.{{AllAcceptedCredentialsOptions/allAcceptedCredentialIds}}</code>:
    1. If the result of [=base64url encoding | base64url decoding=]
        |credentialId| is an error, then return [=a promise rejected with=] a
        {{TypeError}}.
1. Let |p| be the result of executing the [$Asynchronous RP ID validation
    algorithm$] with
    <code>|options|.{{AllAcceptedCredentialsOptions/rpId}}</code>.
1. [=Upon fulfillment=] of |p|, run the following steps [=in parallel=]:
        1. For every [=authenticator=] presently available on this [=client
            platform=], invoke the [=signal method/authenticator
            actions/allAcceptedCredentialIds=] [=authenticator action=] with
            |options| as input.
1. Return |p|.

The <dfn for="signal method/authenticator
actions">allAcceptedCredentialIds</dfn> [=signal method/authenticator
actions=] take an {{AllAcceptedCredentialsOptions}} |options| and are as
follows:
1. Let |userId| be result of [=base64url encoding | base64url decoding=]
    <code>|options|.{{AllAcceptedCredentialsOptions/userId}}</code>.
1. Assertion: |userId| is not an error.
1. Let |credential| be
    <code>[=credentials map=][|options|.{{AllAcceptedCredentialsOptions/rpId}}, |userId|]</code>.
1. If |credential| does not exist, abort these steps.
1. If
    <code>|options|.{{AllAcceptedCredentialsOptions/allAcceptedCredentialIds}}</code>
    does NOT [=list/contain=] the result of [=base64url encoding=] the
    |credential|'s [=public key credential source/id=], then [=map/remove=]
    |credential| from the [=credentials map=] or employ an
    [=authenticator=]-specific procedure to hide it from future [=authentication
    ceremonies=].
1. Else, if |credential| has been hidden by an [=authenticator=]-specific
    procedure, reverse the action so that |credential| is present in future
    [=authentication ceremonies=].

<div class="example">

A user has two credentials with [=credential ids=] that [=base64url encode=] to
`aa` and `bb`. The user deletes the credential `aa` on a [=[WRP]=] provided UI.
The [=[WRP]=] runs:

```javascript
PublicKeyCredential.signalAllAcceptedCredentials({
    rpId: "example.com",
    userId: "aabbcc",  // user handle, base64url.
    allAcceptedCredentialIds: [
        "bb",
    ]
});
```

If the [=authenticator=] is attached at the time of execution, it deletes or
hides the [=credential=] corresponding to `aa` from future [=authentication
ceremonies=].

</div>

Note: [=Authenticators=] might not be attached at the time
{{PublicKeyCredential/signalAllAcceptedCredentials(options)}} is executed.
Therefore, [=[WRPS]=] may choose to run
{{PublicKeyCredential/signalAllAcceptedCredentials(options)}} periodically,
e.g. on every sign in.

Note: Credentials not present in
{{AllAcceptedCredentialsOptions/allAcceptedCredentialIds}} will be removed or
hidden, potentially irreversibly. [=Relying parties=] must exercise care that
valid credential IDs are never omitted from the list. If a valid [=credential
ID=] were accidentally omitted, the [=relying party=] should immediately include
it in {{PublicKeyCredential/signalAllAcceptedCredentials(options)}} as soon as
possible to "un-hide" it, if supported by the [=authenticator=].

[=Authenticators=] SHOULD, whenever possible, prefer hiding [=public key credentials=] for a period of time instead
of permanently removing them, to aid recovery if a [=[WRP]=]
accidentally omits valid [=credential IDs=] from
{{AllAcceptedCredentialsOptions/allAcceptedCredentialIds}}.

#### {{PublicKeyCredential/signalCurrentUserDetails(options)}} #### {#sctn-signalCurrentUserDetails}

The {{PublicKeyCredential/signalCurrentUserDetails(options)|signalCurrentUserDetails}} method signals the user's
current {{PublicKeyCredentialEntity/name}} and {{PublicKeyCredentialUserEntity/displayName}}.

Upon invocation of {{PublicKeyCredential/signalCurrentUserDetails(options)}}, the
[=client=] executes these steps:

1. If the result of [=base64url encoding | base64url decoding=]
    <code>|options|.{{CurrentUserDetailsOptions/userId}}</code> is an error,
    then return [=a promise rejected with=] a {{TypeError}}.
1. Let |p| be the result of executing the [$Asynchronous RP ID validation
    algorithm$] with
    <code>|options|.{{CurrentUserDetailsOptions/rpId}}</code>.
1. [=Upon fulfillment=] of |p|, run the following steps [=in parallel=]:
        1. For every [=authenticator=] presently available on this [=client
            platform=], invoke the [=signal method/authenticator
            actions/currentUserDetails=] [=authenticator action=] with |options|
            as input.
1. Return |p|.

The <dfn for="signal method/authenticator actions">currentUserDetails</dfn>
[=signal method/authenticator action=] takes a {{CurrentUserDetailsOptions}}
|options| and is as follows:
1. Let |userId| be result of [=base64url encoding | base64url decoding=]
    <code>|options|.{{CurrentUserDetailsOptions/userId}}</code>.
1. Assertion: |userId| is not an error.
1. Let |credential| be
    <code>[=credentials map=][|options|.{{CurrentUserDetailsOptions/rpId}}, |userId|]</code>.
1. If |credential| does not exist, abort these steps.
1. Update the |credential|'s [=public key credential source/otherUI=] to match
    <code>|options|.{{CurrentUserDetailsOptions/name}}</code> and
    <code>|options|.{{CurrentUserDetailsOptions/displayName}}</code>.

<div class="example">

A user updates their name on a [=[WRP]=] provided UI. The [=[WRP]=] runs:

```javascript
PublicKeyCredential.signalCurrentUserDetails({
    rpId: "example.com",
    userId: "aabbcc",  // user handle, base64url.
    name: "New user name",
    displayName: "New display name",
});
```

The [=authenticator=] then updates the [=public key credential source/otherUI=]
of the matching credential.

</div>

Note: [=Authenticators=] might not be attached at the time
{{PublicKeyCredential/signalCurrentUserDetails(options)}} is executed.
Therefore, [=[WRPS]=] may choose to run
{{PublicKeyCredential/signalCurrentUserDetails(options)}} periodically, e.g. on
every sign in.

## Authenticator Responses (interface <dfn interface>AuthenticatorResponse</dfn>) ## {#iface-authenticatorresponse}

[=Authenticators=] respond to [=[RP]=] requests by returning an object derived from the
{{AuthenticatorResponse}} interface:

<xmp class="idl">
    [SecureContext, Exposed=Window]
    interface AuthenticatorResponse {
        [SameObject] readonly attribute ArrayBuffer      clientDataJSON;
    };
</xmp>
<div dfn-type="attribute" dfn-for="AuthenticatorResponse">
    :   <dfn>clientDataJSON</dfn>
    ::  This attribute contains a [[#clientdatajson-serialization|JSON-compatible serialization]] of the [=client data=], the [=hash of the serialized client data|hash of which=] is passed to the
        authenticator by the client in its call to either {{CredentialsContainer/create()}} or {{CredentialsContainer/get()}} (i.e., the
        [=client data=] itself is not sent to the authenticator).
</div>

### Information About Public Key Credential (interface <dfn interface>AuthenticatorAttestationResponse</dfn>) ### {#iface-authenticatorattestationresponse}

The {{AuthenticatorAttestationResponse}} interface represents the [=authenticator=]'s response to a client's request
for the creation of a new [=public key credential=]. It contains information about the new credential that can be used to
identify it for later use, and metadata that can be used by the [=[WRP]=] to assess the characteristics of the credential
during registration.

<xmp class="idl">
    [SecureContext, Exposed=Window]
    interface AuthenticatorAttestationResponse : AuthenticatorResponse {
        [SameObject] readonly attribute ArrayBuffer      attestationObject;
        sequence<DOMString>                              getTransports();
        ArrayBuffer                                      getAuthenticatorData();
        ArrayBuffer?                                     getPublicKey();
        COSEAlgorithmIdentifier                          getPublicKeyAlgorithm();
    };
</xmp>
<div dfn-type="attribute" dfn-for="AuthenticatorAttestationResponse">
    :   {{AuthenticatorResponse/clientDataJSON}}
    ::  This attribute, inherited from {{AuthenticatorResponse}}, contains the [=JSON-compatible serialization of client data=] (see
        [[#sctn-attestation]]) passed to the authenticator by the client in order to generate this credential. The
        exact JSON serialization MUST be preserved, as the [=hash of the serialized client data=] has been computed
        over it.

    :   <dfn>attestationObject</dfn>
    ::  This attribute contains an [=attestation object=], which is opaque to, and cryptographically protected against
        tampering by, the client. The [=attestation object=] contains both [=authenticator data=] and an [=attestation
        statement=]. The former contains the AAGUID, a unique [=credential ID=], and the [=credential public key=]. The
        contents of the [=attestation statement=] are determined by the [=attestation statement format=] used by the
        [=authenticator=]. It also contains any additional information that the [=[RP]=]'s server requires to validate the
        [=attestation statement=], as well as to decode and validate the [=authenticator data=] along with the
        [=JSON-compatible serialization of client data=]. For more details, see [[#sctn-attestation]], [[#sctn-generating-an-attestation-object]],
        and [Figure 6](#fig-attStructs).

    :   {{AuthenticatorAttestationResponse/getTransports()}}
    ::  This operation returns the value of {{AuthenticatorAttestationResponse/[[transports]]}}.

    :   {{AuthenticatorAttestationResponse/getAuthenticatorData()}}
    ::  This operation returns the [=authenticator data=] contained within {{AuthenticatorAttestationResponse/attestationObject}}. See [[#sctn-public-key-easy]].

    :   {{AuthenticatorAttestationResponse/getPublicKey()}}
    ::  This operation returns the DER [=SubjectPublicKeyInfo=] of the new credential, or null if this is not available. See [[#sctn-public-key-easy]].

    :   {{AuthenticatorAttestationResponse/getPublicKeyAlgorithm()}}
    ::  This operation returns the {{COSEAlgorithmIdentifier}} of the new credential. See [[#sctn-public-key-easy]].

    :   <dfn>\[[transports]]</dfn>
    ::  This [=internal slot=] contains a sequence of zero or more unique {{DOMString}}s in lexicographical order. These values are the transports that the [=authenticator=] is believed to support, or an empty sequence if the information is unavailable. The values SHOULD be members of {{AuthenticatorTransport}} but [=[RPS]=] SHOULD accept and store unknown values.
</div>

#### Easily accessing credential data #### {#sctn-public-key-easy}

Every user of the {{PublicKeyCredential/[CREATE-METHOD]}} method will need to parse and store the returned [=credential public key=] in order to verify future [=authentication assertions=]. However, the [=credential public key=] is in COSE format [[!RFC9052]], inside the [=credentialPublicKey=] member of the [=attestedCredentialData=], inside the [=authenticator data=], inside the [=attestation object=] conveyed by {{AuthenticatorAttestationResponse}}.{{AuthenticatorAttestationResponse/attestationObject}}. [=[RPS]=] wishing to use [=attestation=] are obliged to do the work of parsing the {{AuthenticatorAttestationResponse/attestationObject}} and obtaining the [=credential public key=] because that public key copy is the one the [=authenticator=] [signed](#signing-procedure). However, many valid WebAuthn use cases do not require [=attestation=]. For those uses, user agents can do the work of parsing, expose the [=authenticator data=] directly, and translate the [=credential public key=] into a more convenient format.

The {{AuthenticatorAttestationResponse/getPublicKey()}} operation thus returns the [=credential public key=] as a [=SubjectPublicKeyInfo=]. This {{ArrayBuffer}} can, for example, be passed to Java's `java.security.spec.X509EncodedKeySpec`, .NET's `System.Security.Cryptography.ECDsa.ImportSubjectPublicKeyInfo`, or Go's `crypto/x509.ParsePKIXPublicKey`.

Use of {{AuthenticatorAttestationResponse/getPublicKey()}} does impose some limitations: by using {{PublicKeyCredentialCreationOptions/pubKeyCredParams}}, a [=[RP]=] can negotiate with the [=authenticator=] to use public key algorithms that the user agent may not understand. However, if the [=[RP]=] does so, the user agent will not be able to translate the resulting [=credential public key=] into [=SubjectPublicKeyInfo=] format and the return value of {{AuthenticatorAttestationResponse/getPublicKey()}} will be null.

User agents MUST be able to return a non-null value for {{AuthenticatorAttestationResponse/getPublicKey()}} when the [=credential public key=] has a {{COSEAlgorithmIdentifier}} value of:
   * -7 (ES256), where [=kty=] is 2 (with uncompressed points) and [=crv=] is 1 (P-256).
   * -257 (RS256).
   * -8 (EdDSA), where [=crv=] is 6 (Ed25519).

A [=SubjectPublicKeyInfo=] does not include information about the signing algorithm (for example, which hash function to use) that is included in the COSE public key. To provide this, {{AuthenticatorAttestationResponse/getPublicKeyAlgorithm()}} returns the {{COSEAlgorithmIdentifier}} for the [=credential public key=].

To remove the need to parse CBOR at all in many cases, {{AuthenticatorAttestationResponse/getAuthenticatorData()}} returns the [=authenticator data=] from {{AuthenticatorAttestationResponse/attestationObject}}. The [=authenticator data=] contains other fields that are encoded in a binary format. However, helper functions are not provided to access them because [=[RPS]=] already need to extract those fields when [getting an assertion](#sctn-getAssertion). In contrast to [credential creation](#sctn-createCredential), where signature verification is [optional](#enumdef-attestationconveyancepreference), [=[RPS]=] should always be verifying signatures from an assertion and thus must extract fields from the signed [=authenticator data=]. The same functions used there will also serve during credential creation.

[=[RPS]=] SHOULD use feature detection before using these functions by testing the value of
<code>'getPublicKey' in AuthenticatorAttestationResponse.prototype</code>.

Note: {{AuthenticatorAttestationResponse/getPublicKey()}} and {{AuthenticatorAttestationResponse/getAuthenticatorData()}}
were only added in Level 2 of this specification.
[=[RPS]=] that require these functions to exist may not interoperate with older user-agents.

### Web Authentication Assertion (interface <dfn interface>AuthenticatorAssertionResponse</dfn>) ### {#iface-authenticatorassertionresponse}

The {{AuthenticatorAssertionResponse}} interface represents an [=authenticator=]'s response to a client's request for
generation of a new [=authentication assertion=] given the [=[WRP]=]'s challenge and OPTIONAL list of credentials it is
aware of. This response contains a cryptographic signature proving possession of the [=credential private key=], and
optionally evidence of [=user consent=] to a specific transaction.

<xmp class="idl">
    [SecureContext, Exposed=Window]
    interface AuthenticatorAssertionResponse : AuthenticatorResponse {
        [SameObject] readonly attribute ArrayBuffer      authenticatorData;
        [SameObject] readonly attribute ArrayBuffer      signature;
        [SameObject] readonly attribute ArrayBuffer?     userHandle;
    };
</xmp>
<div dfn-type="attribute" dfn-for="AuthenticatorAssertionResponse">
    :   {{AuthenticatorResponse/clientDataJSON}}
    ::  This attribute, inherited from {{AuthenticatorResponse}}, contains the [=JSON-compatible serialization of client data=] (see
        [[#dictionary-client-data]]) passed to the authenticator by the client in order to generate this assertion. The
        exact JSON serialization MUST be preserved, as the [=hash of the serialized client data=] has been computed
        over it.

    :   <dfn>authenticatorData</dfn>
    ::  This attribute contains the [=authenticator data=] returned by the authenticator. See [[#sctn-authenticator-data]].

    :   <dfn>signature</dfn>
    ::  This attribute contains the raw signature returned from the authenticator. See [[#sctn-op-get-assertion]].

    :   <dfn>userHandle</dfn>
    ::  This attribute contains the [=user handle=] returned from the authenticator, or null if the authenticator did not return a
        [=user handle=]. See [[#sctn-op-get-assertion]]. The authenticator MUST always return a [=user handle=] if
        the {{PublicKeyCredentialRequestOptions/allowCredentials}} option used in the [=authentication ceremony=] is [=list/is empty|empty=],
        and MAY return one otherwise.
</div>

## Parameters for Credential Generation (dictionary <dfn dictionary>PublicKeyCredentialParameters</dfn>) ## {#dictionary-credential-params}

<xmp class="idl">
    dictionary PublicKeyCredentialParameters {
        required DOMString                    type;
        required COSEAlgorithmIdentifier      alg;
    };
</xmp>

<div dfn-type="dict-member" dfn-for="PublicKeyCredentialParameters">
    This dictionary is used to supply additional parameters when creating a new credential.

    :   <dfn>type</dfn>
    ::  This member specifies the type of credential to be created. The value SHOULD be a member of {{PublicKeyCredentialType}} but [=client platforms=] MUST ignore unknown values, ignoring any {{PublicKeyCredentialParameters}} with an unknown {{PublicKeyCredentialParameters/type}}.

    :   <dfn>alg</dfn>
    ::  This member specifies the cryptographic signature algorithm with which the newly generated credential will be used, and
        thus also the type of asymmetric key pair to be generated, e.g., RSA or Elliptic Curve.

    Note: we use "alg" as the latter member name, rather than spelling-out "algorithm", because it will be serialized into
        a message to the authenticator, which may be sent over a low-bandwidth link.
</div>

## Options for Credential Creation (dictionary <dfn dictionary>PublicKeyCredentialCreationOptions</dfn>) ## {#dictionary-makecredentialoptions}

<xmp class="idl">
    dictionary PublicKeyCredentialCreationOptions {
        required PublicKeyCredentialRpEntity         rp;
        required PublicKeyCredentialUserEntity       user;

        required BufferSource                             challenge;
        required sequence<PublicKeyCredentialParameters>  pubKeyCredParams;

        unsigned long                                timeout;
        sequence<PublicKeyCredentialDescriptor>      excludeCredentials = [];
        AuthenticatorSelectionCriteria               authenticatorSelection;
        sequence<DOMString>                          hints = [];
        DOMString                                    attestation = "none";
        sequence<DOMString>                          attestationFormats = [];
        AuthenticationExtensionsClientInputs         extensions;
    };
</xmp>
<div dfn-type="dict-member" dfn-for="PublicKeyCredentialCreationOptions">
    :   <dfn>rp</dfn>
    ::  This member contains a name and an identifier for the [=[RP]=] responsible for the request.

        Its value's {{PublicKeyCredentialEntity/name}} member is REQUIRED. See [[#dictionary-pkcredentialentity]] for further
        details.

        Its value's {{PublicKeyCredentialRpEntity/id}} member specifies the [=RP ID=] the credential
        should be [=scoped=] to. If omitted, its value will be the {{CredentialsContainer}} object's [=relevant
        settings object=]'s [=environment settings object/origin=]'s [=effective domain=]. See [[#dictionary-rp-credential-params]]
        for further details.

    :   <dfn>user</dfn>
    ::  This member contains names and an identifier for the [=user account=] performing the [=registration=].

        Its value's {{PublicKeyCredentialEntity/name}}, {{PublicKeyCredentialUserEntity/displayName}} and
        {{PublicKeyCredentialUserEntity/id}} members are REQUIRED.
        {{PublicKeyCredentialUserEntity/id}} can be returned as the {{AuthenticatorAssertionResponse/userHandle}}
        in some future [=authentication ceremonies=],
        and is used to overwrite existing [=discoverable credentials=]
        that have the same <code>{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialRpEntity/id}}</code> and <code>{{PublicKeyCredentialCreationOptions/user}}.{{PublicKeyCredentialUserEntity/id}}</code>
        on the same [=authenticator=].
        {{PublicKeyCredentialEntity/name}} and {{PublicKeyCredentialUserEntity/displayName}}
        MAY be used by the [=authenticator=] and [=client=] in future [=authentication ceremonies=]
        to help the user select a [=credential=], but are not returned to the [=[RP]=] as a result of future [=authentication ceremonies=]

        For further details, see [[#dictionary-pkcredentialentity]] and [[#dictionary-user-credential-params]].

    :   <dfn>challenge</dfn>
    ::  This member specifies a challenge that the [=authenticator=] signs, along with other data,
        when producing an [=attestation object=] for the newly created credential.
        See the [[#sctn-cryptographic-challenges]] security consideration.

    :   <dfn>pubKeyCredParams</dfn>
    ::  This member lists the key types and signature algorithms the [=[RP]=] supports,
        ordered from most preferred to least preferred.
        Duplicates are allowed but effectively ignored.
        The [=client=] and [=authenticator=] make a best-effort to create a credential of the most preferred type possible.
        If none of the listed types can be created, the {{CredentialsContainer/create()}} operation fails.

        [=[RPS]=] that wish to support a wide range of [=authenticators=] SHOULD include at least the following {{COSEAlgorithmIdentifier}} values:

        * -8 (EdDSA)
        * -7 (ES256)
        * -257 (RS256)

        Additional signature algorithms can be included as needed.

        The following fully-specified {{COSEAlgorithmIdentifier}} values
        introduced by [[RFC9864]] are NOT RECOMMENDED
        in {{PublicKeyCredentialCreationOptions/pubKeyCredParams}}:

        * -9 (ESP256); use -7 (ES256) instead or in addition.
        * -51 (ESP384); use -35 (ES384) instead or in addition.
        * -52 (ESP512); use -36 (ES512) instead or in addition.
        * -19 (Ed25519); use -8 (EdDSA) instead or in addition.

        Note: Within WebAuthn, the values -9 (ESP256), -51 (ESP384), -52 (ESP512) and -19 (Ed25519)
        represent the same thing respectively as -7 (ES256), -35 (ES384), -36 (ES512) and -8 (EdDSA)
        because of the additional restrictions stated in [[#sctn-alg-identifier]].
        However, they are not interchangeable in practice
        since many implementations support the latter identifiers but not the former ones.
        Therefore the latter identifiers are preferred in {{PublicKeyCredentialCreationOptions/pubKeyCredParams}}
        for backwards compatibility.

    :   <dfn>timeout</dfn>
    ::  This OPTIONAL member specifies a time, in milliseconds, that the [=[RP]=] is willing to wait for the call to complete. This is
        treated as a hint, and MAY be overridden by the [=client=].

    :   <dfn>excludeCredentials</dfn>
    ::  The [=[RP]=] SHOULD use this OPTIONAL member to list any existing [=credentials=] mapped to this [=user account=]
        (as identified by {{PublicKeyCredentialCreationOptions/user}}.{{PublicKeyCredentialUserEntity/id}}).
        This ensures that the new credential is not [=created on=] an [=authenticator=]
        that already [=contains=] a credential mapped to this [=user account=].
        If it would be, the [=client=] is requested to instead guide the user to use a different [=authenticator=],
        or return an error if that fails.

    :   <dfn>authenticatorSelection</dfn>
    ::  The [=[RP]=] MAY use this OPTIONAL member to specify capabilities and settings
        that the [=authenticator=] MUST or SHOULD satisfy to participate in the {{CredentialsContainer/create()}} operation.
        See [[#dictionary-authenticatorSelection]].

    :   <dfn>hints</dfn>
    ::  This OPTIONAL member contains zero or more elements from {{PublicKeyCredentialHint}} to guide the user agent in interacting with the user. Note that the elements have type `DOMString` despite being taken from that enumeration. See [[#sct-domstring-backwards-compatibility]].

    :   <dfn>attestation</dfn>
    ::  The [=[RP]=] MAY use this OPTIONAL member to specify a preference regarding [=attestation conveyance=].
        Its value SHOULD be a member of {{AttestationConveyancePreference}}.
        [=Client platforms=] MUST ignore unknown values, treating an unknown value as if the [=map/exist|member does not exist=].

        The default value is {{AttestationConveyancePreference/none}}.

    :   <dfn>attestationFormats</dfn>
    ::  The [=[RP]=] MAY use this OPTIONAL member to specify a preference regarding the [=attestation=] statement format used by the [=authenticator=].
        Values SHOULD be taken from the IANA "WebAuthn Attestation Statement Format Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]].
        Values are ordered from most preferred to least preferred.
        Duplicates are allowed but effectively ignored.
        This parameter is advisory and the [=authenticator=] MAY use an attestation statement not enumerated in this parameter.

        The default value is the empty list, which indicates no preference.

    :   <dfn>extensions</dfn>
    ::  The [=[RP]=] MAY use this OPTIONAL member to provide [=client extension inputs=]
        requesting additional processing by the [=client=] and [=authenticator=].
        For example, the [=[RP]=] may request that the client returns additional information about the [=credential=] that was created.

        The extensions framework is defined in [[#sctn-extensions]].
        Some extensions are defined in [[#sctn-defined-extensions]];
        consult the IANA "WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]] for an up-to-date list
        of registered [=WebAuthn Extensions=].
</div>

### Public Key Entity Description (dictionary <dfn dictionary>PublicKeyCredentialEntity</dfn>) ### {#dictionary-pkcredentialentity}

The {{PublicKeyCredentialEntity}} dictionary describes a [=user account=], or a [=[WRP]=], which a [=public key credential=] is
associated with or [=scoped=] to, respectively.

<xmp class="idl">
    dictionary PublicKeyCredentialEntity {
        required DOMString    name;
    };
</xmp>
<div dfn-type="dict-member" dfn-for="PublicKeyCredentialEntity">
    :   <dfn>name</dfn>
    ::  A [=human-palatable=] name for the entity. Its function depends on what the {{PublicKeyCredentialEntity}} represents:

          - \[DEPRECATED] When inherited by {{PublicKeyCredentialRpEntity}} it is a [=human-palatable=] identifier for the [=[RP]=], intended only
            for display. For example, "ACME Corporation", "Wonderful Widgets, Inc." or "ОАО Примертех".

            This member is deprecated because many [=clients=] do not display it,
            but it remains a required dictionary member for backwards compatibility.
            [=[RPS]=] MAY, as a safe default, set this equal to the [=RP ID=].

              - [=[RPS]=] SHOULD perform enforcement, as prescribed in Section 2.3 of
                [[!RFC8266]] for the Nickname Profile of the PRECIS FreeformClass [[!RFC8264]],
                when setting {{PublicKeyCredentialEntity/name}}'s value, or displaying the value to the user.

              - [=Clients=] SHOULD perform enforcement, as prescribed in Section 2.3 of
                [[!RFC8266]] for the Nickname Profile of the PRECIS FreeformClass [[!RFC8264]],
                on {{PublicKeyCredentialEntity/name}}'s value prior to displaying the value to the user or
                including the value as a parameter of the [=authenticatorMakeCredential=] operation.

          - When inherited by {{PublicKeyCredentialUserEntity}}, it is a
            [=human-palatable=] identifier for a [=user account=]. This
            identifier is the primary value displayed to users by [=Clients=] to help users
            understand with which [=user account=] a credential is associated.

            Examples of suitable values for this identifier include, "alexm", "+14255551234",
            "alex.mueller@example.com", "alex.mueller@example.com (prod-env)",
            or "alex.mueller@example.com (ОАО Примертех)".

              - The [=[RP]=] MAY let the user choose this value. The [=[RP]=] SHOULD perform enforcement,
                as prescribed in Section 3.4.3 of [[!RFC8265]] for the UsernameCasePreserved Profile of the PRECIS
                IdentifierClass [[!RFC8264]], when setting {{PublicKeyCredentialEntity/name}}'s value, or displaying the value
                to the user.

              - [=Clients=] SHOULD perform enforcement, as prescribed in Section 3.4.3 of [[!RFC8265]]
                for the UsernameCasePreserved Profile of the PRECIS IdentifierClass [[!RFC8264]],
                on {{PublicKeyCredentialEntity/name}}'s value prior to displaying the value to the user or
                including the value as a parameter of the [=authenticatorMakeCredential=] operation.


        When [=clients=], [=client platforms=], or [=authenticators=] display a {{PublicKeyCredentialEntity/name}}'s value, they should always use UI elements to provide a clear boundary around the displayed value, and not allow overflow into other elements [[css-overflow-3]].

        When storing a {{PublicKeyCredentialEntity/name}} member's value,
        the value MAY be truncated as described in [[#sctn-strings-truncation]]
        using a size limit greater than or equal to 64 bytes.
</div>


### Relying Party Parameters for Credential Generation (dictionary <dfn dictionary>PublicKeyCredentialRpEntity</dfn>) ### {#dictionary-rp-credential-params}

The {{PublicKeyCredentialRpEntity}} dictionary is used to supply additional [=[RP]=] attributes when creating a new credential.

<xmp class="idl">
    dictionary PublicKeyCredentialRpEntity : PublicKeyCredentialEntity {
        DOMString      id;
    };
</xmp>

<div dfn-type="dict-member" dfn-for="PublicKeyCredentialRpEntity">
    :   <dfn>id</dfn>
    ::  A unique identifier for the [=[RP]=] entity, which sets the [=RP ID=].
</div>


### User Account Parameters for Credential Generation (dictionary <dfn dictionary>PublicKeyCredentialUserEntity</dfn>) ### {#dictionary-user-credential-params}

The {{PublicKeyCredentialUserEntity}} dictionary is used to supply additional [=user account=] attributes when creating a new
credential.

<xmp class="idl">
    dictionary PublicKeyCredentialUserEntity : PublicKeyCredentialEntity {
        required BufferSource   id;
        required DOMString      displayName;
    };
</xmp>

<div dfn-type="dict-member" dfn-for="PublicKeyCredentialUserEntity">
    :   <dfn>id</dfn>
    ::  The [=user handle=] of the [=user account=].
        A [=user handle=] is an opaque [=byte sequence=] with a maximum size of 64 bytes,
        and is not meant to be displayed to the user.

        To ensure secure operation, authentication and authorization
        decisions MUST be made on the basis of this {{PublicKeyCredentialUserEntity/id}} member,  not the
        {{PublicKeyCredentialUserEntity/displayName}} nor {{PublicKeyCredentialEntity/name}} members. See Section 6.1 of [[!RFC8266]].

        The [=user handle=] MUST NOT contain [PII] about the user, such as a username or e-mail address;
        see [[#sctn-user-handle-privacy]] for details. The [=user handle=] MUST NOT be empty.

        The [=user handle=] SHOULD NOT be a constant value across different [=user accounts=],
        even for [=non-discoverable credentials=], because some authenticators always create [=discoverable credentials=].
        Thus a constant [=user handle=] would prevent a user from using such an authenticator
        with more than one [=user account=] at the [=[RP]=].

    :   <dfn>displayName</dfn>
    ::  A [=human-palatable=] name for the [=user account=], intended only for
        display. The [=[RP]=] SHOULD let the user choose this, and SHOULD NOT restrict the choice
        more than necessary. If no suitable or [=human-palatable=] name is
        available, the [=[RP]=] SHOULD set this value to an empty string.

        Examples of suitable values for this identifier include, "Alex Müller", "Alex Müller (ACME Co.)" or "田中倫".

        - [=[RPS]=] SHOULD perform enforcement, as prescribed in Section 2.3 of
            [[!RFC8266]] for the Nickname Profile of the PRECIS FreeformClass [[!RFC8264]],
            when setting {{PublicKeyCredentialUserEntity/displayName}}'s value to a non-empty string,
            or displaying a non-empty value to the user.

        - [=Clients=] SHOULD perform enforcement, as prescribed in Section 2.3 of
            [[!RFC8266]] for the Nickname Profile of the PRECIS FreeformClass [[!RFC8264]],
            on {{PublicKeyCredentialUserEntity/displayName}}'s value prior to displaying a non-empty value to the user or
            including a non-empty value as a parameter of the [=authenticatorMakeCredential=] operation.

        When [=clients=], [=client platforms=], or [=authenticators=] display a {{PublicKeyCredentialUserEntity/displayName}}'s value, they should always use UI elements to provide a clear boundary around the displayed value, and not allow overflow into other elements [[css-overflow-3]].

        When storing a {{PublicKeyCredentialUserEntity/displayName}} member's value,
        the value MAY be truncated as described in [[#sctn-strings-truncation]]
        using a size limit greater than or equal to 64 bytes.
</div>


### Authenticator Selection Criteria (dictionary <dfn dictionary>AuthenticatorSelectionCriteria</dfn>) ### {#dictionary-authenticatorSelection}

[=[WRPS]=] may use the {{AuthenticatorSelectionCriteria}} dictionary to specify their requirements regarding authenticator
attributes.

<xmp class="idl">
    dictionary AuthenticatorSelectionCriteria {
        DOMString                    authenticatorAttachment;
        DOMString                    residentKey;
        boolean                      requireResidentKey = false;
        DOMString                    userVerification = "preferred";
    };
</xmp>

<div dfn-type="dict-member" dfn-for="AuthenticatorSelectionCriteria">
    :   <dfn>authenticatorAttachment</dfn>
    ::  If this member is present, eligible [=authenticators=] are filtered to be only those authenticators attached with the specified
        [[#enum-attachment|authenticator attachment modality]] (see also [[#sctn-authenticator-attachment-modality]]).
        If this member is absent, then any attachment modality is acceptable.
        The value SHOULD be a member of {{AuthenticatorAttachment}} but [=client platforms=] MUST ignore unknown values,
        treating an unknown value as if the [=map/exist|member does not exist=].

        See also the {{PublicKeyCredential/authenticatorAttachment}} member of {{PublicKeyCredential}},
        which can tell what [=authenticator attachment modality=] was used
        in a successful {{CredentialsContainer/create()}} or {{CredentialsContainer/get()}} operation.

    :   <dfn>residentKey</dfn>
    ::  Specifies the extent to which the [=[RP]=] desires to create a [=client-side discoverable credential=]. For historical reasons the naming retains the deprecated “resident” terminology. The value SHOULD be a member of {{ResidentKeyRequirement}} but [=client platforms=] MUST ignore unknown values, treating an unknown value as if the [=map/exist|member does not exist=]. If no value is given then the effective value is {{ResidentKeyRequirement/required}} if {{requireResidentKey}} is [TRUE] or {{ResidentKeyRequirement/discouraged}} if it is [FALSE] or absent.

        See {{ResidentKeyRequirement}} for the description of {{residentKey}}'s values and semantics.

    :   <dfn>requireResidentKey</dfn>
    ::  This member is retained for backwards compatibility with WebAuthn Level 1 and, for historical reasons, its naming retains the deprecated “resident” terminology for [=discoverable credentials=]. [=[RPS]=] SHOULD set it to [TRUE] if, and only if, {{residentKey}} is set to {{ResidentKeyRequirement/required}}.

    :   <dfn>userVerification</dfn>
    ::  This member specifies the [=[RP]=]'s requirements regarding [=user verification=] for the
        {{CredentialsContainer/create()}} operation.
        The value SHOULD be a member of {{UserVerificationRequirement}} but [=client platforms=] MUST ignore unknown values, treating an unknown value as if the [=map/exist|member does not exist=].

        See {{UserVerificationRequirement}} for the description of {{AuthenticatorSelectionCriteria/userVerification}}'s values and semantics.
</div>


### Authenticator Attachment Enumeration (enum <dfn enum>AuthenticatorAttachment</dfn>) ### {#enum-attachment}

This enumeration's values describe [=authenticators=]' [=authenticator attachment modality|attachment modalities=].
[=[RPS]=] use this to express a preferred [=authenticator attachment modality=]
when calling {{CredentialsContainer/create()|navigator.credentials.create()}}
to [[#sctn-createCredential|create a credential]], and [=clients=] use this to report the [=authenticator attachment modality=]
used to complete a [=registration ceremony|registration=] or [=authentication ceremony=].

<xmp class="idl">
    enum AuthenticatorAttachment {
        "platform",
        "cross-platform"
    };
</xmp>

Note: The {{AuthenticatorAttachment}} enumeration is deliberately not referenced, see [[#sct-domstring-backwards-compatibility]].

<div dfn-type="enum-value" dfn-for="AuthenticatorAttachment">
    :   <dfn>platform</dfn>
    ::  This value indicates [=platform attachment=].

    :   <dfn>cross-platform</dfn>
    ::  This value indicates [=cross-platform attachment=].
</div>

Note: An [=authenticator attachment modality=] selection option is available only in the {{PublicKeyCredential/[CREATE-METHOD]}} operation. The [=[RP]=] may use it to, for example, ensure the user has a [=roaming credential=] for
authenticating on another [=client device=]; or to specifically register a [=platform credential=] for easier reauthentication using a
particular [=client device=]. The {{PublicKeyCredential/[DISCOVER-METHOD]}}
operation has no [=authenticator attachment modality=] selection option.
The [=client=] and user will use whichever [=credential=] is available and convenient at the time,
subject to the {{PublicKeyCredentialRequestOptions/allowCredentials}} option.


### Resident Key Requirement Enumeration (enum <dfn enum>ResidentKeyRequirement</dfn>) ### {#enum-residentKeyRequirement}

<xmp class="idl">
    enum ResidentKeyRequirement {
        "discouraged",
        "preferred",
        "required"
    };
</xmp>

Note: The {{ResidentKeyRequirement}} enumeration is deliberately not referenced, see [[#sct-domstring-backwards-compatibility]].

This enumeration's values describe the [=[RP]=]'s requirements for [=client-side discoverable credentials=] (formerly known as [=resident credentials=] or [=resident keys=]):

<div dfn-type="enum-value" dfn-for="ResidentKeyRequirement">
    :   <dfn>discouraged</dfn>
    ::  The [=[RP]=] prefers creating a [=server-side credential=], but will accept a
        [=client-side discoverable credential=].
        The [=client=] and [=authenticator=] SHOULD create a [=server-side credential=] if possible.

        Note: A [=[RP]=] cannot require that a created credential is a [=server-side credential=] and the [=credProps|Credential Properties Extension=] may not return a value for the {{CredentialPropertiesOutput/rk}} property. Because of this, it may be the case that it does not know if a credential is a [=server-side credential=] or not and thus does not know whether creating a second credential with the same [=user handle=] will evict the first.

    :   <dfn>preferred</dfn>
    ::  The [=[RP]=] strongly prefers creating a [=client-side discoverable credential=], but will accept a
        [=server-side credential=].
        The [=client=] and [=authenticator=] SHOULD create a [=discoverable credential=] if possible.
        For example, the [=client=] SHOULD guide the user through setting up [=user verification=] if needed to create a [=discoverable credential=]. This takes precedence over the setting of {{AuthenticatorSelectionCriteria/userVerification}}.

    :   <dfn>required</dfn>
    ::  The [=[RP]=] requires a [=client-side discoverable credential=].
        The [=client=] MUST return an error if a [=client-side discoverable credential=] cannot be created.
</div>

Note: The [=[RP]=] can seek information on whether or not the authenticator created a [=client-side discoverable credential=]
using the [=resident key credential property=] of the [=credProps|Credential Properties Extension=].
This is useful when values of {{ResidentKeyRequirement/discouraged}} or {{ResidentKeyRequirement/preferred}} are used for
<code>|options|.{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{residentKey}}</code>, because in those cases it is possible for an
[=authenticator=] to create <em>either</em> a [=client-side discoverable credential=] or a [=server-side credential=].


### <dfn>Attestation Conveyance</dfn> Preference Enumeration (enum <dfn enum>AttestationConveyancePreference</dfn>) ### {#enum-attestation-convey}

[=[WRPS]=] may use {{AttestationConveyancePreference}} to specify their preference regarding [=attestation conveyance=]
during credential generation.

<xmp class="idl">
    enum AttestationConveyancePreference {
        "none",
        "indirect",
        "direct",
        "enterprise"
    };
</xmp>

Note: The {{AttestationConveyancePreference}} enumeration is deliberately not referenced, see [[#sct-domstring-backwards-compatibility]].

<div dfn-type="enum-value" dfn-for="AttestationConveyancePreference">
    :   <dfn>none</dfn>
    ::  The [=[RP]=] is not interested in [=authenticator=] [=attestation=]. For example, in order to
        potentially avoid having to obtain [=user consent=] to relay identifying information to the [=[RP]=], or to save a
        roundtrip to an [=Attestation CA=] or [=Anonymization CA=].
        If the [=authenticator=] generates an [=attestation statement=] that is not a [=self attestation=],
        the [=client=] will replace it with a [=None=] attestation statement.

        This is the default, and unknown values fall back to the behavior of this value.

    :   <dfn>indirect</dfn>
    ::  The [=[RP]=] wants to receive a verifiable [=attestation statement=],
        but allows the [=client=] to decide how to obtain such an [=attestation statement=].
        The client MAY replace an authenticator-generated [=attestation statement=] with one generated by an [=Anonymization CA=],
        in order to protect the user's privacy, or to assist [=[RPS]=] with attestation verification in a heterogeneous ecosystem.

        Note: There is no guarantee that the [=[RP]=] will obtain a verifiable [=attestation statement=] in this case.
        For example, in the case that the authenticator employs [=self attestation=]
        and the [=client=] passes the [=attestation statement=] through unmodified.

    :   <dfn>direct</dfn>
    ::  The [=[RP]=] wants to receive the [=attestation statement=] as generated by the [=authenticator=].

    :   <dfn>enterprise</dfn>
    ::  The [=[RP]=] wants to receive an enterprise attestation, which is an [=attestation statement=] that may include information which uniquely identifies the authenticator. This is intended for controlled deployments within an enterprise where the organization wishes to tie registrations to specific authenticators. User agents MUST NOT provide such an attestation unless the user agent or authenticator configuration permits it for the requested [=RP ID=].

        If permitted, the user agent SHOULD signal to the authenticator (at [invocation time](#CreateCred-InvokeAuthnrMakeCred)) that enterprise attestation is requested, and convey the resulting [=/AAGUID=] and [=attestation statement=], unaltered, to the [=[RP]=].
</div>


## Options for Assertion Generation (dictionary <dfn dictionary>PublicKeyCredentialRequestOptions</dfn>) ## {#dictionary-assertion-options}

The {{PublicKeyCredentialRequestOptions}} dictionary supplies {{CredentialsContainer/get()}} with the data it needs to generate
an assertion. Its {{PublicKeyCredentialRequestOptions/challenge}} member MUST be present, while its other members are OPTIONAL.

<xmp class="idl">
    dictionary PublicKeyCredentialRequestOptions {
        required BufferSource                challenge;
        unsigned long                        timeout;
        DOMString                            rpId;
        sequence<PublicKeyCredentialDescriptor> allowCredentials = [];
        DOMString                            userVerification = "preferred";
        sequence<DOMString>                  hints = [];
        AuthenticationExtensionsClientInputs extensions;
    };
</xmp>

<dl dfn-type="dict-member" dfn-for="PublicKeyCredentialRequestOptions">
    :   <dfn>challenge</dfn>
    ::  This member specifies a challenge that the [=authenticator=] signs, along with other data, when producing an
        [=authentication assertion=]. See the [[#sctn-cryptographic-challenges]] security consideration.

    :   <dfn>timeout</dfn>
    ::  This OPTIONAL member specifies a time, in milliseconds, that the [=[RP]=] is willing to wait for the call to complete.
        The value is treated as a hint, and MAY be overridden by the [=client=].

    :   <dfn>rpId</dfn>
    ::  This OPTIONAL member specifies the [=RP ID=] claimed by the [=[RP]=].
        The [=client=] MUST verify that the [=[RP]=]'s [=origin=] matches the [=scope=] of this [=RP ID=].
        The [=authenticator=] MUST verify
        that this [=RP ID=] exactly equals the [=rpId=] of the [=credential=] to be used for the [=authentication ceremony=].

        If not specified, its value will
        be the {{CredentialsContainer}} object's [=relevant settings object=]'s [=environment settings object/origin=]'s
        [=effective domain=].

    :   <dfn>allowCredentials</dfn>
    ::  This OPTIONAL member is used by the [=client=] to find [=authenticators=] eligible for this [=authentication ceremony=].
        It can be used in two ways:

          - If the [=user account=] to authenticate is already identified (e.g., if the user has entered a username),
            then the [=[RP]=] SHOULD use this member to list
            [=credential descriptor for a credential record|credential descriptors for credential records=] in the [=user account=].
            This SHOULD usually include all [=credential records=] in the [=user account=].

            The [=list/items=] SHOULD specify {{PublicKeyCredentialDescriptor/transports}} whenever possible.
            This helps the [=client=] optimize the user experience for any given situation.
            Also note that the [=[RP]=] does not need to filter the list when requesting [=user verification=] &mdash;
            the [=client=] will automatically ignore non-eligible credentials
            if {{PublicKeyCredentialRequestOptions/userVerification}} is set to {{UserVerificationRequirement/required}}.

            See also the [[#sctn-credential-id-privacy-leak]] privacy consideration.

          - If the [=user account=] to authenticate is not already identified,
            then the [=[RP]=] MAY leave this member [=list/empty=] or unspecified.
            In this case, only [=discoverable credentials=] will be utilized in this [=authentication ceremony=],
            and the [=user account=] MAY be identified by the {{AuthenticatorAssertionResponse/userHandle}}
            of the resulting {{AuthenticatorAssertionResponse}}.
            If the available [=authenticators=] [=contain=] more than one [=discoverable credential=] [=scoped=] to the [=[RP]=],
            the credentials are displayed by the [=client platform=] or [=authenticator=]
            for the user to select from (see [step 7](#authenticatorGetAssertion-prompt-select-credential)
            of [[#sctn-op-get-assertion]]).

        If not [=list/empty=], the client MUST return an error if none of the listed credentials can be used.

        The list is ordered in descending order of preference: the first item in the list is the most
        preferred credential, and the last is the least preferred.

    :   <dfn>userVerification</dfn>
    ::  This OPTIONAL member specifies the [=[RP]=]'s requirements regarding [=user verification=] for the
        {{CredentialsContainer/get()}} operation. The value SHOULD be a member of {{UserVerificationRequirement}} but [=client platforms=] MUST ignore unknown values, treating an unknown value as if the [=map/exist|member does not exist=]. Eligible authenticators are filtered to only those capable of satisfying this requirement.

        See {{UserVerificationRequirement}} for the description of {{AuthenticatorSelectionCriteria/userVerification}}'s values and semantics.

    :   <dfn>hints</dfn>
    ::  This OPTIONAL member contains zero or more elements from {{PublicKeyCredentialHint}} to guide the user agent in interacting with the user. Note that the elements have type `DOMString` despite being taken from that enumeration. See [[#sct-domstring-backwards-compatibility]].

    :   <dfn>extensions</dfn>
    ::  The [=[RP]=] MAY use this OPTIONAL member to provide [=client extension inputs=]
        requesting additional processing by the [=client=] and [=authenticator=].

        The extensions framework is defined in [[#sctn-extensions]].
        Some extensions are defined in [[#sctn-defined-extensions]];
        consult the IANA "WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]] for an up-to-date list
        of registered [=WebAuthn Extensions=].
</dl>


## Abort Operations with `AbortSignal` ## {#sctn-abortoperation}

Developers are encouraged to leverage the {{AbortController}} to manage the
{{PublicKeyCredential/[CREATE-METHOD]}} and {{PublicKeyCredential/[DISCOVER-METHOD]}} operations.
See [[dom#abortcontroller-api-integration]] section for detailed instructions.

    Note: [[dom#abortcontroller-api-integration]] section specifies that web platform APIs integrating with the
    {{AbortController}} must reject the promise immediately once the {{AbortSignal}} is [=AbortSignal/aborted=].
    Given the complex inheritance and parallelization structure of the {{PublicKeyCredential/[CREATE-METHOD]}}
    and {{PublicKeyCredential/[DISCOVER-METHOD]}} methods, the algorithms for the two APIs fulfills this
    requirement by checking the [=AbortSignal/aborted=] property in three places. In the case of
    {{PublicKeyCredential/[CREATE-METHOD]}}, the [=AbortSignal/aborted=] property is checked first in
    [[credential-management-1#algorithm-create]] immediately before calling {{Credential/[CREATE-METHOD]}},
    then in [[#sctn-createCredential]] right before [=authenticator sessions=] start, and finally
    during [=authenticator sessions=]. The same goes for
    {{PublicKeyCredential/[DISCOVER-METHOD]}}.

The [=visibility states|visibility=] and [=focus=] state of the {{Window}} object determines whether the
{{PublicKeyCredential/[CREATE-METHOD]}} and {{PublicKeyCredential/[DISCOVER-METHOD]}} operations
should continue. When the {{Window}} object associated with the [=Document=] loses focus,
{{PublicKeyCredential/[CREATE-METHOD]}} and {{PublicKeyCredential/[DISCOVER-METHOD]}} operations
SHOULD be aborted.


## WebAuthn Extensions Inputs and Outputs ## {#sctn-extensions-inputs-outputs}

The subsections below define the data types used for conveying [=WebAuthn extension=] inputs and outputs.

Note: [=Authenticator extension outputs=] are conveyed as a part of [=authenticator data=] (see [Table 1](#table-authData)).

Note: The types defined below &mdash; {{AuthenticationExtensionsClientInputs}} and {{AuthenticationExtensionsClientOutputs}} &mdash; are applicable to both [=registration extensions=] and [=authentication extensions=]. The "Authentication..." portion of their names should be regarded as meaning "WebAuthentication..."


### Authentication Extensions Client Inputs (dictionary {{AuthenticationExtensionsClientInputs}}) ### {#iface-authentication-extensions-client-inputs}

<xmp class="idl">
    dictionary AuthenticationExtensionsClientInputs {
    };
</xmp>

This is a dictionary containing the [=client extension input=] values for zero or more [=WebAuthn Extensions=].


### Authentication Extensions Client Outputs (dictionary {{AuthenticationExtensionsClientOutputs}}) ### {#iface-authentication-extensions-client-outputs}

<xmp class="idl">
    dictionary AuthenticationExtensionsClientOutputs {
    };
</xmp>

This is a dictionary containing the [=client extension output=] values for zero or more [=WebAuthn Extensions=].


### Authentication Extensions Authenticator Inputs (CDDL type `AuthenticationExtensionsAuthenticatorInputs`) ### {#iface-authentication-extensions-authenticator-inputs}

```
AuthenticationExtensionsAuthenticatorInputs = {
  * $$extensionInput
} .within { * tstr => any }
```

The [=CDDL=] type `AuthenticationExtensionsAuthenticatorInputs` defines a [=CBOR=] map
containing the [=authenticator extension input=] values for zero or more [=WebAuthn Extensions=].
Extensions can add members as described in [[#sctn-extension-request-parameters]].

This type is not exposed to the [=[RP]=], but is used by the [=client=] and [=authenticator=].


### Authentication Extensions Authenticator Outputs (CDDL type `AuthenticationExtensionsAuthenticatorOutputs`) ### {#iface-authentication-extensions-authenticator-outputs}

```
AuthenticationExtensionsAuthenticatorOutputs = {
  * $$extensionOutput
} .within { * tstr => any }
```

The [=CDDL=] type `AuthenticationExtensionsAuthenticatorOutputs` defines a [=CBOR=] map
containing the [=authenticator extension output=] values for zero or more [=WebAuthn Extensions=].
Extensions can add members as described in [[#sctn-extension-request-parameters]].


## Supporting Data Structures ## {#sctn-supporting-data-structures}

The [=public key credential=] type uses certain data structures that are specified in supporting specifications. These are as
follows.


### Client Data Used in [=WebAuthn Signatures=] (dictionary <dfn dictionary>CollectedClientData</dfn>) ### {#dictionary-client-data}

The <dfn>client data</dfn> represents the contextual bindings of both the [=[WRP]=] and the [=client=]. It is a key-value
mapping whose keys are strings. Values can be any type that has a valid encoding in JSON. Its structure is defined by the
following Web IDL.

Note: The {{CollectedClientData}} may be extended in the future. Therefore it's critical when parsing to be tolerant of unknown keys and of any reordering of the keys. See also [[#clientdatajson-verification]].

<xmp class="idl">
    dictionary CollectedClientData {
        required DOMString           type;
        required DOMString           challenge;
        required DOMString           origin;
        boolean                      crossOrigin;
        DOMString                    topOrigin;
    };

    dictionary TokenBinding {
        required DOMString status;
        DOMString id;
    };

    enum TokenBindingStatus { "present", "supported" };
</xmp>

<div dfn-type="dict-member" dfn-for="CollectedClientData">
    :   <dfn>type</dfn>
    ::  This member contains the string "webauthn.create" when creating new credentials, and "webauthn.get" when getting an
        assertion from an existing credential. The purpose of this member is to prevent certain types of signature confusion
        attacks (where an attacker substitutes one legitimate signature for another).

    :   <dfn>challenge</dfn>
    ::  This member contains the base64url encoding of the challenge provided by the [=[RP]=]. See the [[#sctn-cryptographic-challenges]]
        security consideration.

    :   <dfn>origin</dfn>
    ::  This member contains the fully qualified [=origin=] of the requester, as provided to the authenticator by the client, in
        the syntax defined by [[!RFC6454]].

    :   <dfn>crossOrigin</dfn>
    ::  This OPTIONAL member contains the inverse of the `sameOriginWithAncestors` argument value
        that was passed into the [=internal method=].

    :   <dfn>topOrigin</dfn>
    ::  This OPTIONAL member contains the fully qualified [=top-level origin=] of the requester, in the syntax defined
        by [[!RFC6454]]. It is set only if the call was made from context that is not [=same-origin with its
        ancestors=], i.e. if {{CollectedClientData/crossOrigin}} is [TRUE].

        <!-- Setting explicit dfn ID (this becomes the fragment part of the anchor URL) for backwards compatibility;
             without this Bikeshed generates the ID "collectedclientdata-tokenbinding". -->
    :   \[RESERVED] <dfn dfn id="dom-collectedclientdata-tokenbinding">tokenBinding</dfn>
    ::  This OPTIONAL member contains information about the state of the [=Token Binding=] protocol [[!TokenBinding]] used when communicating
        with the [=[RP]=]. Its absence indicates that the client doesn't support token binding

        Note: While [=Token Binding=] was present in Level 1 and Level 2 of WebAuthn, its use is not expected in Level 3. The [=CollectedClientData/tokenBinding=] field is reserved so that it will not be reused for a different purpose.

        <div dfn-type="dict-member" dfn-for="TokenBinding">
            :   <dfn>status</dfn>
            ::  This member SHOULD be a member of {{TokenBindingStatus}} but [=client platforms=] MUST ignore unknown values, treating an unknown value as if the [=CollectedClientData/tokenBinding=] [=map/exist|member does not exist=]. When known, this member is one of the following:

                <div dfn-type="enum-value" dfn-for="TokenBindingStatus">
                    :   <dfn>supported</dfn>
                    ::  Indicates the client supports token binding, but it was not negotiated when communicating with the [=[RP]=].

                    :   <dfn>present</dfn>
                    ::  Indicates token binding was used when communicating with the [=[RP]=]. In this case, the
                        {{TokenBinding/id}} member MUST be present.
                </div>

                Note: The {{TokenBindingStatus}} enumeration is deliberately not referenced, see [[#sct-domstring-backwards-compatibility]].

            :   <dfn>id</dfn>
            ::  This member MUST be present if {{TokenBinding/status}} is {{TokenBindingStatus/present}}, and MUST be a [=base64url
                encoding=] of the [=Token Binding ID=] that was used when communicating with the [=[RP]=].
        </div>

        Note: Obtaining a [=Token Binding ID=] is a [=client platform=]-specific operation.

    The {{CollectedClientData}} structure is used by the client to compute the following quantities:

    : <dfn dfn>JSON-compatible serialization of client data</dfn>
    :: This is the result of performing the [JSON-compatible serialization algorithm](#clientdatajson-serialization) on the {{CollectedClientData}} dictionary.

    : <dfn dfn>Hash of the serialized client data</dfn>
    :: This is the hash (computed using SHA-256) of the [=JSON-compatible serialization of client data=], as constructed by the client.
</div>

#### Serialization #### {#clientdatajson-serialization}

The serialization of the {{CollectedClientData}} is a subset of the algorithm for [=serialize JSON to bytes|JSON-serializing to bytes=]. I.e. it produces a valid JSON encoding of the {{CollectedClientData}} but also provides additional structure that may be exploited by verifiers to avoid integrating a full JSON parser. While verifiers are recommended to perform standard JSON parsing, they may use the [more limited algorithm](#clientdatajson-verification) below in contexts where a full JSON parser is too large. This verification algorithm requires only [=base64url encoding=], appending of bytestrings (which could be implemented by writing into a fixed template), and simple conditional checks (assuming that inputs are known not to need escaping).

The serialization algorithm works by appending successive byte strings to an, initially empty, partial result until the complete result is obtained.

1. Let |result| be an empty byte string.
1. Append 0x7b2274797065223a (`{"type":`) to |result|.
1. Append [=CCDToString=]({{CollectedClientData/type}}) to |result|.
1. Append 0x2c226368616c6c656e6765223a (`,"challenge":`) to |result|.
1. Append [=CCDToString=]({{CollectedClientData/challenge}}) to |result|.
1. Append 0x2c226f726967696e223a (`,"origin":`) to |result|.
1. Append [=CCDToString=]({{CollectedClientData/origin}}) to |result|.
1. Append 0x2c2263726f73734f726967696e223a (`,"crossOrigin":`) to |result|.
1. If {{CollectedClientData/crossOrigin}} is not present, or is `false`:
    1. Append 0x66616c7365 (`false`) to |result|.
1. Otherwise:
    1. Append 0x74727565 (`true`) to |result|.
1. If {{CollectedClientData/topOrigin}} is present:
    1. Append 0x2c22746f704f726967696e223a (`,"topOrigin":`) to |result|.
    1. Append [=CCDToString=]({{CollectedClientData/topOrigin}}) to |result|.
1. Create a temporary copy of the {{CollectedClientData}} and remove the fields {{CollectedClientData/type}}, {{CollectedClientData/challenge}}, {{CollectedClientData/origin}}, {{CollectedClientData/crossOrigin}} (if present), and {{CollectedClientData/topOrigin}} (if present).
1. If no fields remain in the temporary copy then:
    1. Append 0x7d (`}`) to |result|.
1. Otherwise:
    1. Invoke [=serialize JSON to bytes=] on the temporary copy to produce a byte string |remainder|.
    1. Append 0x2c (`,`) to |result|.
    1. Remove the leading byte from |remainder|.
    1. Append |remainder| to |result|.
1. The result of the serialization is the value of |result|.

The function <dfn>CCDToString</dfn> is used in the above algorithm and is defined as:

1. Let |encoded| be an empty byte string.
1. Append 0x22 (`"`) to |encoded|.
1. Invoke [ToString](https://tc39.es/ecma262/#sec-tostring) on the given object to convert to a string.
1. For each code point in the resulting string, if the code point:
    <dl class="switch">
        : is in the set {U+0020, U+0021, U+0023&ndash;U+005B, U+005D&ndash;U+10FFFF}
        :: Append the UTF-8 encoding of that code point to |encoded|.

        : is U+0022
        :: Append 0x5c22 (`\"`) to |encoded|.

        : is U+005C
        :: Append 0x5c5c (<kbd>\\</kbd>) to |encoded|.

        : otherwise
        :: Append 0x5c75 (`\u`) to |encoded|, followed by four, lower-case hex digits that, when interpreted as a base-16 number, represent that code point.
    </dl>
1. Append 0x22 (`"`) to |encoded|.
1. The result of this function is the value of |encoded|.

#### Limited Verification Algorithm #### {#clientdatajson-verification}

Verifiers may use the following algorithm to verify an encoded {{CollectedClientData}} if they cannot support a full JSON parser:

1. The inputs to the algorithm are:
    1. A bytestring, |clientDataJSON|, that contains {{AuthenticatorResponse/clientDataJSON}}&thinsp;&mdash;&thinsp;the serialized {{CollectedClientData}} that is to be verified.
    1. A string, |type|, that contains the expected {{CollectedClientData/type}}.
    1. A byte string, |challenge|, that contains the challenge byte string that was given in the {{PublicKeyCredentialRequestOptions}} or {{PublicKeyCredentialCreationOptions}}.
    1. A string, |origin|, that contains the expected {{CollectedClientData/origin}} that issued the request to the user agent.
    1. An optional string, |topOrigin|, that contains the expected {{CollectedClientData/topOrigin}} that issued the request to the user agent, if available.
    1. A boolean, |requireTopOrigin|, that is true if, and only if, the verification should fail
        if |topOrigin| is defined and the {{CollectedClientData/topOrigin}} attribute is not present in |clientDataJSON|.

        This means that the verification algorithm is backwards compatible
        with the [[webauthn-2-20210408#clientdatajson-serialization|JSON-compatible serialization algorithm]]
        in Web Authentication Level 2 [[webauthn-2-20210408]]
        if, and only if, |requireTopOrigin| is [FALSE].

1. Let |expected| be an empty byte string.
1. Append 0x7b2274797065223a (`{"type":`) to |expected|.
1. Append [=CCDToString=](|type|) to |expected|.
1. Append 0x2c226368616c6c656e6765223a (`,"challenge":`) to |expected|.
1. Perform [=base64url encoding=] on |challenge| to produce a string, |challengeBase64|.
1. Append [=CCDToString=](|challengeBase64|) to |expected|.
1. Append 0x2c226f726967696e223a (`,"origin":`) to |expected|.
1. Append [=CCDToString=](|origin|) to |expected|.
1. Append 0x2c2263726f73734f726967696e223a (`,"crossOrigin":`) to |expected|.
1. If |topOrigin| is defined:
    1. Append 0x74727565 (`true`) to |expected|.
    1. If |requireTopOrigin| is true
        or if 0x2c22746f704f726967696e223a (`,"topOrigin":`) is a prefix
        of the substring of |clientDataJSON| beginning at the offset equal to the length of |expected|:
        1. Append 0x2c22746f704f726967696e223a (`,"topOrigin":`) to |expected|.
        1. Append [=CCDToString=](|topOrigin|) to |expected|.
1. Otherwise, i.e. |topOrigin| is not defined:
    1. Append 0x66616c7365 (`false`) to |expected|.
1. If |expected| is not a prefix of |clientDataJSON| then the verification has failed.
1. If |clientDataJSON| is not at least one byte longer than |expected| then the verification has failed.
1. If the byte of |clientDataJSON| at the offset equal to the length of |expected|:
    <dl class="switch">
        : is 0x7d
        :: The verification is successful.

        : is 0x2c
        :: The verification is successful.

        : otherwise
        :: The verification has failed.
    </dl>

#### Future development #### {#clientdatajson-development}

In order to remain compatible with the [limited verification algorithm](#clientdatajson-verification), future versions of this specification must not remove any of the fields {{CollectedClientData/type}}, {{CollectedClientData/challenge}}, {{CollectedClientData/origin}}, {{CollectedClientData/crossOrigin}}, or {{CollectedClientData/topOrigin}} from {{CollectedClientData}}. They also must not change the [serialization algorithm](#clientdatajson-verification) to change the order in which those fields are serialized, or insert new fields between them.

If additional fields are added to {{CollectedClientData}} then verifiers that employ the [limited verification algorithm](#clientdatajson-verification) will not be able to consider them until the two algorithms above are updated to include them. Once such an update occurs then the added fields inherit the same limitations as described in the previous paragraph. Such an algorithm update would have to accomodate serializations produced by previous versions. I.e. the verification algorithm would have to handle the fact that a sixth key&ndash;value pair may not appear sixth (or at all) if generated by a user agent working from a previous version.

### Credential Type Enumeration (enum <dfn enum>PublicKeyCredentialType</dfn>) ### {#enum-credentialType}

<xmp class="idl">
    enum PublicKeyCredentialType {
        "public-key"
    };
</xmp>

Note: The {{PublicKeyCredentialType}} enumeration is deliberately not referenced, see [[#sct-domstring-backwards-compatibility]].

<div dfn-type="enum-value" dfn-for="PublicKeyCredentialType">
    This enumeration defines the valid credential types. It is an extension point; values can be added to it in the future, as
    more credential types are defined. The values of this enumeration are used for versioning the Authentication Assertion and
    attestation structures according to the type of the authenticator.

    Currently one credential type is defined, namely "<dfn>public-key</dfn>".

</div>


### Credential Descriptor (dictionary <dfn dictionary>PublicKeyCredentialDescriptor</dfn>) ### {#dictionary-credential-descriptor}

<xmp class="idl">
    dictionary PublicKeyCredentialDescriptor {
        required DOMString                    type;
        required BufferSource                 id;
        sequence<DOMString>                   transports;
    };
</xmp>

This dictionary identifies a specific [=public key credential=].
It is used in {{CredentialsContainer/create()}} to prevent creating duplicate credentials on the same [=authenticator=],
and in {{CredentialsContainer/get()}} to determine if and how the credential can currently be reached by the [=client=].

The [=credential descriptor for a credential record=] is a subset of the properties of that [=credential record=],
and mirrors some fields of the {{PublicKeyCredential}} object returned by
{{CredentialsContainer/create()}} and {{CredentialsContainer/get()}}.

<div dfn-type="dict-member" dfn-for="PublicKeyCredentialDescriptor">
    :   <dfn>type</dfn>
    ::  This member contains the type of the [=public key credential=] the caller is referring to. The value SHOULD be a member of {{PublicKeyCredentialType}} but [=client platforms=] MUST ignore any {{PublicKeyCredentialDescriptor}} with an unknown {{PublicKeyCredentialDescriptor/type}}.
        However, if all elements are ignored due to unknown {{PublicKeyCredentialDescriptor/type}},
        then that MUST result in an error since an empty {{PublicKeyCredentialRequestOptions/allowCredentials}} is semantically distinct.

        This SHOULD be set to the value of the [$credential record/type$] item of the [=credential record=]
        representing the identified [=public key credential source=].
        This mirrors the {{Credential/type}} field of {{PublicKeyCredential}}.

    :   <dfn>id</dfn>
    ::  This member contains the [=credential ID=] of the [=public key credential=] the caller is referring to.

        This SHOULD be set to the value of the [$credential record/id$] item of the [=credential record=]
        representing the identified [=public key credential source=].
        This mirrors the {{PublicKeyCredential/rawId}} field of {{PublicKeyCredential}}.

    :   <dfn>transports</dfn>
    ::  This OPTIONAL member contains a hint as to how the [=client=] might communicate with the [=managing authenticator=] of the
        [=public key credential=] the caller is referring to. The values SHOULD be members of {{AuthenticatorTransport}} but [=client platforms=] MUST ignore unknown values.

        This SHOULD be set to the value of the [$credential record/transports$] item of the [=credential record=]
        representing the identified [=public key credential source=].
        This mirrors the <code>{{PublicKeyCredential/response}}.{{AuthenticatorAttestationResponse/getTransports()}}</code> method
        of the {{PublicKeyCredential}} structure created by a {{CredentialsContainer/create()}} operation.
</div>


### Authenticator Transport Enumeration (enum <dfn enum>AuthenticatorTransport</dfn>) ### {#enum-transport}

<xmp class="idl">
    enum AuthenticatorTransport {
        "usb",
        "nfc",
        "ble",
        "smart-card",
        "hybrid",
        "internal"
    };
</xmp>

Note: The {{AuthenticatorTransport}} enumeration is deliberately not referenced, see [[#sct-domstring-backwards-compatibility]].

<div dfn-type="enum-value" dfn-for="AuthenticatorTransport">
    [=Authenticators=] may implement various [[#enum-transport|transports]] for communicating with [=clients=]. This enumeration
    defines hints as to how clients might communicate with a particular authenticator in order to obtain an assertion for a
    specific credential. Note that these hints represent the [=[WRP]=]'s best belief as to how an authenticator may be reached. A
    [=[RP]=] will typically learn of the supported transports for a [=public key credential=] via
    {{AuthenticatorAttestationResponse/getTransports()}}.

    :   <dfn>usb</dfn>
    ::  Indicates the respective [=authenticator=] can be contacted over removable USB.

    :   <dfn>nfc</dfn>
    ::  Indicates the respective [=authenticator=] can be contacted over Near Field Communication (NFC).

    :   <dfn>ble</dfn>
    ::  Indicates the respective [=authenticator=] can be contacted over Bluetooth Smart (Bluetooth Low Energy / BLE).

    :   <dfn>smart-card</dfn>
    ::  Indicates the respective [=authenticator=] can be contacted over ISO/IEC 7816 smart card with contacts.

    :   <dfn>hybrid</dfn>
    ::  Indicates the respective [=authenticator=] can be contacted using a combination of (often separate) data-transport and proximity mechanisms. This supports, for example, authentication on a desktop computer using a smartphone.

    :   <dfn>internal</dfn>
    ::  Indicates the respective [=authenticator=] is contacted using a [=client device=]-specific transport,
        i.e., it is a [=platform authenticator=].
        These authenticators are not removable from the [=client device=].
</div>


### Cryptographic Algorithm Identifier (typedef {{COSEAlgorithmIdentifier}}) ### {#sctn-alg-identifier}

<xmp class="idl">
    typedef long COSEAlgorithmIdentifier;
</xmp>

<div dfn-type="typedef" dfn-for="COSEAlgorithmIdentifier">
    A {{COSEAlgorithmIdentifier}}'s value is a number identifying a cryptographic algorithm.
    The algorithm identifiers SHOULD be values registered in the IANA COSE Algorithms registry [[!IANA-COSE-ALGS-REG]],
    for instance, <code>-7</code> for "ES256" and <code>-257</code> for "RS256".

    The COSE algorithms registry leaves degrees of freedom to be specified by other parameters in a [=COSE key=]. In order to promote interoperability, this specification makes the following additional guarantees of [=credential public keys=]:
        1. Keys with algorithm -7 (ES256) MUST specify 1 (P-256) as the [=crv=] parameter and MUST NOT use the compressed point form.
        1. Keys with algorithm -9 (ESP256) MUST NOT use the compressed point form.
        1. Keys with algorithm -35 (ES384) MUST specify 2 (P-384) as the [=crv=] parameter and MUST NOT use the compressed point form.
        1. Keys with algorithm -51 (ESP384) MUST NOT use the compressed point form.
        1. Keys with algorithm -36 (ES512) MUST specify 3 (P-521) as the [=crv=] parameter and MUST NOT use the compressed point form.
        1. Keys with algorithm -52 (ESP512) MUST NOT use the compressed point form.
        1. Keys with algorithm -8 (EdDSA) MUST specify 6 (Ed25519) as the [=crv=] parameter. (These always use a compressed form in COSE.)

    These restrictions align with the recommendation in [=Section 2.1=] of [[!RFC9053]].
</div>

Note: There are many checks neccessary to correctly implement signature verification using these algorithms. One of these is that, when processing uncompressed elliptic-curve points, implementations should check that the point is actually on the curve. This check is highlighted because it's judged to be at particular risk of falling through the gap between a cryptographic library and other code.

### User Verification Requirement Enumeration (enum <dfn enum>UserVerificationRequirement</dfn>) ### {#enum-userVerificationRequirement}

<xmp class="idl">
    enum UserVerificationRequirement {
        "required",
        "preferred",
        "discouraged"
    };
</xmp>

A [=[WRP]=] may require [=user verification=] for some of its operations but not for others, and may use this type to express its
needs.

Note: The {{UserVerificationRequirement}} enumeration is deliberately not referenced, see [[#sct-domstring-backwards-compatibility]].

<div dfn-type="enum-value" dfn-for="UserVerificationRequirement">
    :   <dfn>required</dfn>
    ::  The [=[RP]=] requires [=user verification=] for the operation and will fail the overall [=ceremony=] if the
        response does not have the [=authData/flags/UV=] [=flag=] set.
        The [=client=] MUST return an error if [=user verification=] cannot be performed.

    :   <dfn>preferred</dfn>
    ::  The [=[RP]=] prefers [=user verification=] for the operation if possible, but will not fail the
        operation if the response does not have the [=authData/flags/UV=] [=flag=] set.

    :   <dfn>discouraged</dfn>
    ::  The [=[RP]=] does not want [=user verification=] employed during the operation (e.g., in the
        interest of minimizing disruption to the user interaction flow).
</div>

### Client Capability Enumeration (enum <dfn enum>ClientCapability</dfn>) ### {#enum-clientCapability}

<xmp class="idl">
    enum ClientCapability {
        "conditionalCreate",
        "conditionalGet",
        "hybridTransport",
        "passkeyPlatformAuthenticator",
        "userVerifyingPlatformAuthenticator",
        "relatedOrigins",
        "signalAllAcceptedCredentials",
        "signalCurrentUserDetails",
        "signalUnknownCredential"
    };
</xmp>

This enumeration defines a limited set of client capabilities which a [=[WRP]=] may evaluate to offer certain workflows and experiences to users.

[=[RPS]=] may use the {{PublicKeyCredential/getClientCapabilities()}} method of {{PublicKeyCredential}}
to obtain a description of available capabilities.

Note: The {{ClientCapability}} enumeration is deliberately not referenced, see [[#sct-domstring-backwards-compatibility]].

<div dfn-type="enum-value" dfn-for="ClientCapability">
    :   <dfn>conditionalCreate</dfn>
    ::  The [=WebAuthn Client=] is capable of {{CredentialMediationRequirement/conditional}} mediation for [=registration ceremonies=]..

        See [[#sctn-createCredential]] for more details.

    :   <dfn>conditionalGet</dfn>
    ::  The [=WebAuthn Client=] is capable of {{CredentialMediationRequirement/conditional}} mediation for [=authentication ceremonies=].

        This capability is equivalent to {{PublicKeyCredential/isConditionalMediationAvailable()}} resolving to [TRUE].

        See [[#sctn-getAssertion]] for more details.

    :   <dfn>hybridTransport</dfn>
    ::  The [=WebAuthn Client=] supports usage of the {{AuthenticatorTransport/hybrid}} transport.

    :   <dfn>passkeyPlatformAuthenticator</dfn>
    ::  The [=WebAuthn Client=] supports usage of a [=passkey platform authenticator=], locally and/or via {{AuthenticatorTransport/hybrid}} transport.

    :   <dfn>userVerifyingPlatformAuthenticator</dfn>
    ::  The [=WebAuthn Client=] supports usage of a [=user-verifying platform authenticator=].

    :   <dfn>relatedOrigins</dfn>
    ::  The [=WebAuthn Client=] supports [[#sctn-related-origins|Related Origin Requests]].

    :   <dfn>signalAllAcceptedCredentials</dfn>
    ::  The [=WebAuthn Client=] supports {{PublicKeyCredential/signalAllAcceptedCredentials()}}.

    :   <dfn>signalCurrentUserDetails</dfn>,
    ::  The [=WebAuthn Client=] supports {{PublicKeyCredential/signalCurrentUserDetails()}}.

    :   <dfn>signalUnknownCredential</dfn>
    ::  The [=WebAuthn Client=] supports {{PublicKeyCredential/signalUnknownCredential()}}.
</div>

### User-agent Hints Enumeration (enum <dfn enum>PublicKeyCredentialHint</dfn>) ### {#enum-hints}

<xmp class="idl">
    enum PublicKeyCredentialHint {
        "security-key",
        "client-device",
        "hybrid",
    };
</xmp>

Note: The {{PublicKeyCredentialHint}} enumeration is deliberately not referenced, see [[#sct-domstring-backwards-compatibility]].

<div dfn-type="enum-value" dfn-for="PublicKeyCredentialHint">
    [=[WRPS]=] may use this enumeration to communicate hints to the user-agent about how a request may be best completed. These hints are not requirements, and do not bind the user-agent, but may guide it in providing the best experience by using contextual information that the [=[RP]=] has about the request. Hints are provided in order of decreasing preference so, if two hints are contradictory, the first one controls. Hints may also overlap: if a more-specific hint is defined a [=[RP]=] may still wish to send less specific ones for user-agents that may not recognise the more specific one. In this case the most specific hint should be sent before the less-specific ones.
    If the same hint appears more than once, its second and later appearances are ignored.

    Hints MAY contradict information contained in credential {{PublicKeyCredentialDescriptor/transports}} and {{AuthenticatorSelectionCriteria/authenticatorAttachment}}. When this occurs, the hints take precedence. (Note that {{PublicKeyCredentialDescriptor/transports}} values are not provided when using [=discoverable credentials=], leaving hints as the only avenue for expressing some aspects of such a request.)

    :   <dfn>security-key</dfn>
    ::  Indicates that the [=[RP]=] believes that users will satisfy this request with a physical security key. For example, an enterprise [=[RP]=] may set this hint if they have issued security keys to their employees and will only accept those [=authenticators=] for [=registration ceremony|registration=] and [=authentication ceremony|authentication=].

        For compatibility with older user agents, when this hint is used in {{PublicKeyCredentialCreationOptions}}, the {{AuthenticatorSelectionCriteria/authenticatorAttachment}} SHOULD be set to {{AuthenticatorAttachment/cross-platform}}.

    :   <dfn>client-device</dfn>
    ::  Indicates that the [=[RP]=] believes that users will satisfy this request with a [=platform authenticator=] attached to the [=client device=].

        For compatibility with older user agents, when this hint is used in {{PublicKeyCredentialCreationOptions}}, the {{AuthenticatorSelectionCriteria/authenticatorAttachment}} SHOULD be set to {{AuthenticatorAttachment/platform}}.

    :   <dfn>hybrid</dfn>
    ::  Indicates that the [=[RP]=] believes that users will satisfy this request with general-purpose [=authenticators=] such as smartphones. For example, a consumer [=[RP]=] may believe that only a small fraction of their customers possesses dedicated security keys. This option also implies that the local [=platform authenticator=] should not be promoted in the UI.

        For compatibility with older user agents, when this hint is used in {{PublicKeyCredentialCreationOptions}}, the {{AuthenticatorSelectionCriteria/authenticatorAttachment}} SHOULD be set to {{AuthenticatorAttachment/cross-platform}}.

</div>


## Permissions Policy integration ## {#sctn-permissions-policy}

This specification defines two [=policy-controlled features=] identified by
the feature-identifier tokens "<code><dfn data-lt="publickey-credentials-create-feature" export>publickey-credentials-create</dfn></code>"
and "<code><dfn data-lt="publickey-credentials-get-feature" export>publickey-credentials-get</dfn></code>".
Their [=default allowlists=] are both '<code>self</code>'. [[!Permissions-Policy]]

A {{Document}}'s [=Document/permissions policy=] determines whether any content in that <a href="https://html.spec.whatwg.org/multipage/dom.html#documents">document</a> is
[=allowed to use|allowed to successfully invoke=] the [=Web Authentication API=], i.e., via <code><a idl for="CredentialsContainer" lt="create()">navigator.credentials.create({publicKey:..., ...})</a></code> or
<code><a idl for="CredentialsContainer" lt="get()">navigator.credentials.get({publicKey:..., ...})</a></code>
If disabled in any document, no content in the document will be [=allowed to use=]
the foregoing methods: attempting to do so will [return an error](https://www.w3.org/2001/tag/doc/promises-guide#errors).

Note: Algorithms specified in [[!CREDENTIAL-MANAGEMENT-1]] perform the actual permissions policy evaluation. This is because such policy evaluation needs to occur when there is access to the [=current settings object=]. The {{PublicKeyCredential/[CREATE-METHOD]}} and {{PublicKeyCredential/[DISCOVER-METHOD]}} [=internal methods=] do not have such access since they are invoked [=in parallel=] by {{CredentialsContainer}}'s <a abstract-op>Create a `Credential`</a> and <a abstract-op>Request a `Credential`</a> abstract operations [[!CREDENTIAL-MANAGEMENT-1]].



## Using Web Authentication within <code>iframe</code> elements ## {#sctn-iframe-guidance}

The [=Web Authentication API=] is disabled by default in cross-origin <{iframe}>s.
To override this default policy and indicate that a cross-origin <{iframe}> is allowed to invoke the [=Web Authentication API=]'s
{{PublicKeyCredential/[CREATE-METHOD]}} and {{PublicKeyCredential/[DISCOVER-METHOD]}} methods,
specify the <{iframe/allow}> attribute on the <{iframe}> element and include the
<code>[=publickey-credentials-create-feature|publickey-credentials-create=]</code> or
<code>[=publickey-credentials-get-feature|publickey-credentials-get=]</code>
feature-identifier token, respectively, in the <{iframe/allow}> attribute's value.

[=[RPS]=] utilizing the WebAuthn API in an embedded context should review [[#sctn-seccons-visibility]] regarding [=UI redressing=] and its possible mitigations.

## Using Web Authentication across related origins ## {#sctn-related-origins}

By default, Web Authentication requires that the [=RP ID=] be equal to the [=determines the set of origins on which the public key credential may be exercised|origin=]'s [=effective domain=], or a [=is a registrable domain suffix of or is equal to|registrable domain suffix=] of the [=determines the set of origins on which the public key credential may be exercised|origin=]'s [=effective domain=].

This can make deployment challenging for large environments where multiple country-specific domains are in use (e.g. example.com vs example.co.uk vs example.sg), where alternative or brand domains are required (e.g. myexampletravel.com vs examplecruises.com), and/or where platform as a service providers are used to support mobile apps. 

[=[WRPS]=] can opt in to allowing [=WebAuthn Clients=] to enable a credential to be created and used across a limited set of related [=origin|origins=].
Such [=[RPS]=] MUST choose a common [=RP ID=] to use across all ceremonies from related origins.

A JSON document MUST be hosted at the `webauthn` well-known URL [[!RFC8615]] for the [=RP ID=], and MUST be served using HTTPS. The JSON document MUST be returned as follows:

    - The content type MUST be `application/json`.
    - The top-level JSON object MUST contain a key named `origins` whose value MUST be an array of one or more strings containing web origins.

For example, for the RP ID `example.com`:

<xmp class="json" highlight="json">
{
    "origins": [
        "https://example.co.uk",
        "https://example.de",
        "https://example.sg",
        "https://example.net",
        "https://exampledelivery.com",
        "https://exampledelivery.co.uk",
        "https://exampledelivery.de",
        "https://exampledelivery.sg",
        "https://myexamplerewards.com",
        "https://examplecars.com"
    ]
}
</xmp>

[=WebAuthn Clients=] supporting this feature MUST support at least five [=registrable origin labels=]. Client policy SHOULD define an upper limit to prevent abuse.

Requests to this well-known endpoint by [=WebAuthn Clients=] MUST be made without [=request/credentials mode|credentials=], without a [=request/referrer policy|referrer=],
and using the `https:` [=scheme=]. When following redirects, [=WebAuthn Clients=] MUST explicitly require all redirects to also use the `https:` [=scheme=].

[=WebAuthn Clients=] supporting this feature SHOULD include {{ClientCapability/relatedOrigins}} in their response to [[#sctn-getClientCapabilities|getClientCapabilities()]].

### Validating Related Origins ### {#sctn-validating-relation-origin}

The <dfn abstract-op>related origins validation procedure</dfn>, given arguments |callerOrigin| and |rpIdRequested|, is as follows:

1. Let |maxLabels| be the maximum number of [=registrable origin labels=] allowed by client policy.
1. Fetch the `webauthn` well-known URL [[!RFC8615]] for the RP ID |rpIdRequested| (i.e., <code>https://|rpIdRequested|/.well-known/webauthn</code>) without [=request/credentials mode|credentials=], without a [=request/referrer policy|referrer=] and using the `https:` [=scheme=].
    1. If the fetch fails, the response does not have a content type of `application/json`, or does not have a status code (after following redirects) of 200, then throw a "{{SecurityError}}" {{DOMException}}.
    1. If the body of the resource is not a valid JSON object, then throw a "{{SecurityError}}" {{DOMException}}.
    1. If the value of the |origins| property of the JSON object is missing, or is not an array of strings, then throw a "{{SecurityError}}" {{DOMException}}.
1. Let |labelsSeen| be a new empty [=set=].
1. [=set/For each=] |originItem| of |origins|:
    1. Let |url| be the result of running the [=URL parser=] with |originItem| as the input. If that fails, [=continue=].
    1. Let |domain| be the [=effective domain=] of |url|. If that is null, [=continue=].
    1. Let |label| be [=registrable origin label=] of |domain|.
    1. If |label| is empty or null, [=continue=].
    1. If the [=set/size=] of |labelsSeen| is greater than or equal to |maxLabels| and |labelsSeen| does not [=set/contain=] |label|, [=continue=].
    1. If |callerOrigin| and |url| are [=same origin=], return [TRUE].
    1. If the [=set/size=] of |labelsSeen| is less than |maxLabels|, [=set/append=] |label| to |labelsSeen|.
1. Return [FALSE].

# WebAuthn <dfn>Authenticator Model</dfn> # {#sctn-authenticator-model}

[[#sctn-api|The Web Authentication API]] implies a specific abstract functional model for a [=[WAA]=]. This section
describes that [=authenticator model=].

[=Client platforms=] MAY implement and expose this abstract model in any way desired. However, the behavior of the client's Web
Authentication API implementation, when operating on the authenticators supported by that [=client platform=], MUST be indistinguishable
from the behavior specified in [[#sctn-api]].

Note: [[!FIDO-CTAP]] is an example of a concrete instantiation of this model, but it is one in which there are differences in the data it returns and those expected by the [[#sctn-api|WebAuthn API]]'s algorithms. The CTAP2 response messages are CBOR maps constructed using integer keys rather than the string keys defined in this specification for the same objects. The [=client=] is expected to perform any needed transformations on such data. The [[!FIDO-CTAP]] specification details the mapping between CTAP2 integer keys and WebAuthn string keys in Section [=§6. Authenticator API=].

For authenticators, this model defines the logical operations that they MUST support, and the data formats that they expose to
the client and the [=[WRP]=]. However, it does not define the details of how authenticators communicate with the [=client device=],
unless they are necessary for interoperability with [=[RPS]=]. For instance, this abstract model does not define protocols for
connecting authenticators to clients over transports such as USB or NFC. Similarly, this abstract model does not define specific
error codes or methods of returning them; however, it does define error behavior in terms of the needs of the client. Therefore,
specific error codes are mentioned as a means of showing which error conditions MUST be distinguishable (or not) from each other
in order to enable a compliant and secure client implementation.

[=[RPS]=] may influence authenticator selection, if they deem necessary, by stipulating various authenticator characteristics
when [[#sctn-createCredential|creating credentials]] and/or when [[#sctn-getAssertion|generating assertions]], through use of
[[#dictionary-makecredentialoptions|credential creation options]] or [[#dictionary-assertion-options|assertion generation options]],
respectively. The algorithms underlying the [[#sctn-api|WebAuthn API]] marshal these options and pass them to the applicable
[[#sctn-authenticator-ops|authenticator operations]] defined below.

In this abstract model, the authenticator provides key management and cryptographic signatures. It can be embedded in the
WebAuthn client or housed in a separate device entirely. The authenticator itself can contain a cryptographic module which
operates at a higher security level than the rest of the authenticator. This is particularly important for authenticators that
are embedded in the WebAuthn client, as in those cases this cryptographic module (which may, for example, be a TPM) could be
considered more trustworthy than the rest of the authenticator.

Each authenticator stores a <dfn for=authenticator>credentials map</dfn>, a [=map=] from ([=rpId=], [=public key credential source/userHandle=]) to
[=public key credential source=].

Additionally, each authenticator has an Authenticator Attestation Globally Unique Identifier or <dfn>AAGUID</dfn>, which is a 128-bit identifier
indicating the type (e.g. make and model) of the authenticator. The AAGUID MUST be chosen by its maker to be identical across all substantially identical
authenticators made by that maker, and different (with high probability) from the AAGUIDs of all other types of authenticators. The AAGUID for a given type
of authenticator SHOULD be randomly generated to ensure this. The [=[RP]=] MAY use the AAGUID to infer certain properties of the authenticator, such as
certification level and strength of key protection, using information from other sources. The [=[RP]=] MAY use the AAGUID to attempt to identify the maker of
the authenticator without requesting and verifying [=attestation=], but the AAGUID is not provably authentic without [=attestation=].

The primary function of the authenticator is to provide [=WebAuthn signatures=], which are bound to various contextual data. These
data are observed and added at different levels of the stack as a signature request passes from the server to the
authenticator. In verifying a signature, the server checks these bindings against expected values. These contextual bindings
are divided in two: Those added by the [=[RP]=] or the client, referred to as [=client data=]; and those added by the authenticator,
referred to as the [=authenticator data=]. The authenticator signs over the [=client data=], but is otherwise not interested in
its contents. To save bandwidth and processing requirements on the authenticator, the client hashes the [=client data=] and
sends only the result to the authenticator. The authenticator signs over the combination of the
[=hash of the serialized client data=], and its own [=authenticator data=].

The goals of this design can be summarized as follows.

- The scheme for generating signatures should accommodate cases where the link between the [=client device=] and authenticator
    is very limited, in bandwidth and/or latency. Examples include Bluetooth Low Energy and Near-Field Communication.

- The data processed by the authenticator should be small and easy to interpret in low-level code. In particular, authenticators
    should not have to parse high-level encodings such as JSON.

- Both the [=client=] and the authenticator should have the flexibility to add contextual bindings as needed.

- The design aims to reuse as much as possible of existing encoding formats in order to aid adoption and implementation.

Authenticators produce cryptographic signatures for two distinct purposes:
1. An <dfn>attestation signature</dfn> is produced when a new [=public key credential=] is created via an
    [=authenticatorMakeCredential=] operation. An [=attestation signature=] provides cryptographic
    proof of certain properties of the [=authenticator=] and the credential. For instance, an [=attestation signature=]
    asserts the [=authenticator=] type (as denoted by its AAGUID) and the [=credential public key=]. The [=attestation
    signature=] is signed by an [=attestation private key=], which is chosen depending on the type of [=attestation=] desired.
    For more details on [=attestation=], see [[#sctn-attestation]].
2. An <dfn>assertion signature</dfn> is produced when the [=authenticatorGetAssertion=] method is invoked. It represents an
    assertion by the [=authenticator=] that the user has [=user consent|consented=] to a specific transaction, such as logging
    in, or completing a purchase. Thus, an [=assertion signature=] asserts that the [=authenticator=] possessing a particular
    [=credential private key=] has established, to the best of its ability, that the user requesting this transaction is the
    same user who [=user consent|consented=] to creating that particular [=public key credential=]. It also asserts additional
    information, termed [=client data=], that may be useful to the caller, such as the means by which [=user consent=] was
    provided, and the prompt shown to the user by the [=authenticator=]. The [=assertion signature=] format is illustrated in
    [Figure 4, below](#fig-signature).

The term <dfn>WebAuthn signature</dfn> refers to both [=attestation signatures=] and [=assertion signatures=].
The formats of these signatures, as well as the procedures for generating them, are specified below.

## Authenticator Data ## {#sctn-authenticator-data}

The <dfn>authenticator data</dfn> structure encodes contextual bindings made by the [=authenticator=]. These bindings are
controlled by the authenticator itself, and derive their trust from the [=[WRP]=]'s assessment of the security properties of the
authenticator. In one extreme case, the authenticator may be embedded in the client, and its bindings may be no more trustworthy
than the [=client data=]. At the other extreme, the authenticator may be a discrete entity with high-security hardware and
software, connected to the client over a secure channel. In both cases, the [=[RP]=] receives the [=authenticator data=] in the same
format, and uses its knowledge of the authenticator to make trust decisions.

The [=authenticator data=] has a compact but extensible encoding. This is desired since authenticators can be devices with
limited capabilities and low power requirements, with much simpler software stacks than the [=client platform=].

The [=authenticator data=] structure is a byte array of 37 bytes or more,
laid out as shown in <a href="#table-authData">Table <span class="table-ref-following"></span></a>.


<figure id="table-authData" class="table">
    <table class="complex data longlastcol" dfn-for="authData">
        <tr>
            <th>Name</th>
            <th>Length (in bytes)</th>
            <th>Description</th>
        </tr>
        <tr>
            <td><dfn>rpIdHash</dfn></td>
            <td>32</td>
            <td>
                SHA-256 hash of the [=RP ID=] the [=public key credential|credential=] is [=scoped=] to.
            </td>
        </tr>
        <tr>
            <td><dfn>flags</dfn></td>
            <td>1</td>
            <td dfn-for="authData/flags">
                Flags (bit 0 is the least significant bit):
                - Bit 0: [=User Present=] (<dfn>UP</dfn>) result.
                    - `1` means the user is [=user present|present=].
                    - `0` means the user is not [=user present|present=].
                - Bit 1: Reserved for future use (`RFU1`).
                - Bit 2: [=User Verified=] (<dfn>UV</dfn>) result.
                    - `1` means the user is [=user verified|verified=].
                    - `0` means the user is not [=user verified|verified=].
                - Bit 3: [=Backup Eligibility=] (<dfn>BE</dfn>).
                    - `1` means the [=public key credential source=] is [=backup eligible=].
                    - `0` means the [=public key credential source=] is not [=backup eligible=].
                - Bit 4: [=Backup State=] (<dfn>BS</dfn>).
                    - `1` means the [=public key credential source=] is currently [=backed up=].
                    - `0` means the [=public key credential source=] is not currently [=backed up=].
                - Bit 5: Reserved for future use (`RFU2`).
                - Bit 6: [=Attested credential data=] included (<dfn>AT</dfn>).
                    - Indicates whether the authenticator added [=attested credential data=].
                - Bit 7: Extension data included (<dfn>ED</dfn>).
                    - Indicates if the [=authenticator data=] has [=authData/extensions=].
            </td>
        </tr>
        <tr>
            <td><dfn>signCount</dfn></td>
            <td>4</td>
            <td>[=Signature counter=], 32-bit unsigned big-endian integer.</td>
        </tr>
        <tr>
            <td><dfn>attestedCredentialData</dfn></td>
            <td>variable (if present)</td>
            <td>
                [=attested credential data=] (if present). See [[#sctn-attested-credential-data]] for details. Its length depends on
                the [=credentialIdLength|length=] of the [=credentialId|credential ID=] and [=credentialPublicKey|credential public
                key=] being attested.
            </td>
        </tr>
        <tr>
            <td><dfn>extensions</dfn></td>
            <td>variable (if present)</td>
            <td>
                Extension-defined [=authenticator data=]. This is a [=CBOR=] [[!RFC8949]] map with [=extension identifiers=] as keys,
                and [=authenticator extension outputs=] as values. See [[#sctn-extensions]] for details.
            </td>
        </tr>
    </table>
    <figcaption>
        [=Authenticator data=] layout. The names in the Name column are only for reference within this document, and are not
        present in the actual representation of the [=authenticator data=].
    </figcaption>
</figure>

The [=RP ID=] is originally received from the [=client=] when the credential is created, and again when an [=assertion=] is generated.
However, it differs from other [=client data=] in some important ways. First, unlike the [=client data=], the [=RP ID=] of a
credential does not change between operations but instead remains the same for the lifetime of that credential. Secondly, it is
validated by the authenticator during the [=authenticatorGetAssertion=] operation, by verifying that the [=RP ID=] that
the requested [=public key credential|credential=] is [=scoped=] to exactly matches the [=RP ID=] supplied by the [=client=].

[=Authenticators=] <dfn for="authenticator data">perform the following steps to generate an [=authenticator data=] structure</dfn>:

- Hash [=RP ID=] using SHA-256 to generate the [=rpIdHash=].

- The [=UP=] [=flag=] SHALL be set if and only if the authenticator performed a [=test of user presence=].
    The [=authData/flags/UV=] [=flag=] SHALL be set if and only if the authenticator performed [=user verification=].
    The `RFU` bits SHALL be set to zero.

    Note: If the authenticator performed both a [=test of user presence=] and [=user verification=],
    possibly combined in a single [=authorization gesture=],
    then the authenticator will set both the [=UP=] [=flag=] and the [=authData/flags/UV=] [=flag=].

- The [=BE=] [=flag=] SHALL be set if and only if the credential is a [=multi-device credential=]. 
    This value MUST NOT change after a [=registration ceremony=] as defined in [[#sctn-credential-backup]].

- The [=BS=] [=flag=] SHALL be set if and only if the credential is a [=multi-device credential=] and is currently [=backed up=].

    If the backup status of a credential is uncertain or the authenticator suspects a problem with the backed up credential,
        the [=BS=] [=flag=] SHOULD NOT be set.

- For [=attestation signatures=], the authenticator MUST set the [=AT=] [=flag=] and include the <code>[=attestedCredentialData=]</code>.
    For [=assertion signatures=], the [=AT=] [=flag=] MUST NOT be set and the <code>[=attestedCredentialData=]</code> MUST NOT be included.

- If the authenticator does not include any [=authData/extensions|extension data=], it MUST set the [=authData/flags/ED=] [=flag=] to zero, and to one if
    [=authData/extensions|extension data=] is included.

<a href="#fig-authData">Figure <span class="figure-num-following"></span></a> shows a visual representation of the [=authenticator data=] structure.

<figure id="fig-authData">
    <img no-autosize src="images/fido-signature-formats-figure1.svg">
    <figcaption>[=Authenticator data=] layout.</figcaption>
</figure>

<div class="note">
    <span class="marker">Note:</span>
    The [=authenticator data=] describes its own length: If the [=AT=] and [=authData/flags/ED=] [=flags=] are not set, it is always 37 bytes long.
    The [=attested credential data=] (which is only present if the [=AT=] [=flag=] is set) describes its own length. If the [=authData/flags/ED=] [=flag=] is set, then the total length is 37 bytes plus the length of the [=attested credential data=] (if the [=AT=] [=flag=] is set), plus the length of the [=authData/extensions=] output (a [=CBOR=] map) that
    follows.

    Determining [=attested credential data=]'s length, which is variable, involves determining <code>[=credentialPublicKey=]</code>'s beginning location given the preceding <code>[=credentialid|credentialId=]</code>'s [=credentialidlength|length=], and then determining the <code>[=credentialPublicKey=]</code>'s length (see also [=Section 7=] of [[!RFC9052]]).
</div>

### <dfn>Signature Counter</dfn> Considerations ### {#sctn-sign-counter}

Authenticators SHOULD implement a [=signature counter=] feature. These counters are conceptually stored for each credential
by the authenticator, or globally for the authenticator as a whole. The initial value of a credential's [=signature counter=] is specified in the <code>[=authData/signCount=]</code>
value of the [=authenticator data=] returned by [=authenticatorMakeCredential=]. The [=signature counter=] is incremented for each successful
[=authenticatorGetAssertion=] operation by some positive value, and subsequent values are returned to the [=[WRP]=] within the
[=authenticator data=] again. The [=signature counter=]'s purpose is to aid [=[RPS]=] in detecting cloned authenticators. Clone
detection is more important for authenticators with limited protection measures.

Authenticators that do not implement a [=signature counter=]
leave the <code>[=authData/signCount=]</code> in the [=authenticator data=] constant at zero.

A [=[RP]=] stores the [=signature counter=] of the most recent [=authenticatorGetAssertion=] operation. (Or the counter from the [=authenticatorMakeCredential=] operation if no [=authenticatorGetAssertion=] has ever been performed on a credential.) In subsequent
[=authenticatorGetAssertion=] operations, the [=[RP]=] compares the stored [=signature counter=] value with the new
<code>[=authData/signCount=]</code> value returned in the assertion's [=authenticator data=]. If either is non-zero, and the new <code>[=authData/signCount=]</code> value is less than or equal to the stored value, a cloned authenticator may exist, or the authenticator may be malfunctioning,
or a race condition might exist where the relying party is receiving and processing assertions
in an order other than the order they were generated at the authenticator.

Detecting a [=signature counter=] mismatch does not indicate whether the current operation was performed by a cloned authenticator or the original authenticator.  [=[RPS]=] should address this situation appropriately relative to their individual situations, i.e., their risk tolerance or operational factors that might result in an acceptable reason for non-increasing values.

Authenticators:
- SHOULD implement per credential [=signature counters=].  This prevents the
    [=signature counter=] value from being shared between [=[RPS]=] and being possibly employed
    as a correlation handle for the user. Authenticators MAY implement a global [=signature counter=],
    i.e., on a per-authenticator basis, but this is less privacy-friendly for users.

- SHOULD ensure that the [=signature counter=] value does not
    accidentally decrease  (e.g., due to hardware failures).


### FIDO U2F Signature Format Compatibility ### {#sctn-fido-u2f-sig-format-compat}

The format for [=assertion signatures=], which sign over the concatenation of an [=authenticator data=] structure and the [=hash
of the serialized client data=], are compatible with the FIDO U2F authentication signature format (see [=Section 5.4=] of
[[FIDO-U2F-Message-Formats]]).

This is because the first 37 bytes of the signed data in a FIDO U2F authentication response message constitute a valid
[=authenticator data=] structure, and the remaining 32 bytes are the [=hash of the serialized client data=]. In this
[=authenticator data=] structure, the <code>[=rpIdHash=]</code> is the FIDO U2F [=application parameter=], all
<code>[=flags=]</code> except <code>[=UP=]</code> are always zero, and the <code>[=attestedCredentialData=]</code> and
<code>[=authData/extensions=]</code> are never present. FIDO U2F authentication signatures can therefore be verified by
the same procedure as other [=assertion signatures=] generated by the [=authenticatorGetAssertion=] operation.

### Credential Backup State ### {#sctn-credential-backup}

Credential [=backup eligibility=] and current [=backup state=] is conveyed by the [=authData/flags/BE=] and [=authData/flags/BS=] [=flags=] in the [=authenticator data=], as
defined in <a href="#table-authData">Table <span class="table-ref-previous"></span></a>.

The value of the [=authData/flags/BE=] [=flag=] is set during [=authenticatorMakeCredential=] operation and MUST NOT change.

The value of the [=authData/flags/BS=] [=flag=] may change over time based on the current state of the [=public key credential source=]. <a href="#table-backupStates">Table <span class="table-ref-following"></span></a> below defines
valid combinations and their meaning.

<figure id="table-backupStates" class="table">
    <table class="complex data longlastcol">
            <tr>
            <th>[=authData/flags/BE=]</th>
            <th>[=authData/flags/BS=]</th>
            <th>Description</th>
        </tr>
        <tr>
            <td>`0`</td>
            <td>`0`</td>
            <td>
                The credential is a [=single-device credential=].
            </td>
        </tr>
        <tr>
            <td>`0`</td>
            <td>`1`</td>
            <td>
                This combination is not allowed.
            </td>
        </tr>
        <tr>
            <td>`1`</td>
            <td>`0`</td>
            <td>
                The credential is a [=multi-device credential=] and is not currently [=backed up=].
            </td>
        </tr>
        <tr>
            <td>`1`</td>
            <td>`1`</td>
            <td>
                The credential is a [=multi-device credential=] and is currently [=backed up=].
            </td>
        </tr>
    </table>
    <figcaption>
        [=authData/flags/BE=] and [=authData/flags/BS=] [=flag=] combinations
    </figcaption>
</figure>

It is RECOMMENDED that [=[RPS]=] store the most recent value of these [=flags=] with the [=user account=] for future evaluation.

The following is a non-exhaustive list of how [=[RPS]=] might use these [=flags=]:

    - Requiring additional [=authenticators=]:

        When the [=authData/flags/BE=] [=flag=] is set to `0`, the credential is a [=single-device credential=] and the [=generating authenticator=] will never
        allow the credential to be backed up.

        A [=single-device credential=] is not resilient to single device loss. [=[RPS]=] SHOULD ensure that each [=user account=]
        has additional [=authenticators=] [=registration ceremony|registered=] and/or an account recovery process in place.
        For example, the user could be prompted to set up an additional [=authenticator=], such as a [=roaming authenticator=] or an
        [=authenticator=] that is capable of [=multi-device credentials=].

    - Upgrading a user to a password-free account:

        When the [=authData/flags/BS=] [=flag=] changes from `0` to `1`, the [=authenticator=] is signaling that the [=credential=] is backed up and is protected from single device loss.

        The [=[RP]=] MAY choose to prompt the user to upgrade their account security and remove their password.

    - Adding an additional factor after a state change:

        When the [=authData/flags/BS=] [=flag=] changes from `1` to `0`, the [=authenticator=] is signaling that the [=credential=] is no longer backed up,
        and no longer protected from single device loss. This could be the result of the user actions, such as disabling the backup service,
        or errors, such as issues with the backup service.

        When this transition occurs, the [=[RP]=] SHOULD guide the user through a process to validate their other authentication factors.
        If the user does not have another credential for their account, they SHOULD be guided through adding an additional credential
        to ensure they do not lose access to their account. For example, the user could be prompted to set up an additional [=authenticator=],
        such as a [=roaming authenticator=] or an [=authenticator=] that is capable of [=multi-device credentials=].

## Authenticator Taxonomy ## {#sctn-authenticator-taxonomy}

Many use cases are dependent on the capabilities of the [=authenticator=] used.
This section defines some terminology for those capabilities, their most important combinations,
and which use cases those combinations enable.

For example:

- When authenticating for the first time on a particular [=client device=], a [=roaming authenticator=] is typically needed
    since the user doesn't yet have a [=platform credential=] on that [=client device=].
- For subsequent re-authentication on the same [=client device=], a [=platform authenticator=] is likely the most convenient
    since it's built directly into the [=client device=] rather than being a separate device that the user may have to locate.
- For [=second-factor=] authentication in addition to a traditional username and password, any [=authenticator=] can be used.
- Passwordless [=multi-factor=] authentication requires an [=authenticator=]
    capable of [=user verification=], and in some cases also [=discoverable credential capable=].
- A laptop computer might support connecting to [=roaming authenticators=] via USB and Bluetooth,
    while a mobile phone might only support NFC.

The above examples illustrate the primary <dfn>authenticator type</dfn> characteristics:

- Whether the [=authenticator=] is a [=roaming authenticator|roaming=] or [=platform authenticator|platform=] authenticator,
    or in some cases both &mdash; the [=authenticator attachment modality=].
    A [=roaming authenticator=] can support one or more [[#enum-transport|transports]] for communicating with the [=client=].
- Whether the authenticator is capable of [=user verification=] &mdash; the [=authentication factor capability=].
- Whether the authenticator is [=discoverable credential capable=] &mdash; the [=credential storage modality=].

These characteristics are independent and may in theory be combined in any way,
but <a href="#table-authenticatorTypes">Table <span class="table-ref-following"></span></a>
lists and names some [=authenticator types=] of particular interest.


<figure id="table-authenticatorTypes" class="table">
    <table class="data">
        <thead>
            <tr>
                <th> [=Authenticator Type=] </th>
                <th> [=Authenticator Attachment Modality=] </th>
                <th> [=Credential Storage Modality=] </th>
                <th> [=Authentication Factor Capability=] </th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th> <dfn>Second-factor platform authenticator</dfn> </th>
                <td> [=platform attachment|platform=] </td>
                <td> Either </td>
                <td> [=Single-factor capable=] </td>
            </tr>
            <tr>
                <th> <dfn>User-verifying platform authenticator</dfn> </th>
                <td> [=platform attachment|platform=] </td>
                <td> Either </td>
                <td> [=Multi-factor capable=] </td>
            </tr>
            <tr>
                <th> <dfn>Second-factor roaming authenticator</dfn> </th>
                <td> [=cross-platform attachment|cross-platform=] </td>
                <td> [=server-side credential storage modality|Server-side storage=] </td>
                <td> [=Single-factor capable=] </td>
            </tr>
            <tr>
                <th> <dfn>Passkey roaming authenticator</dfn> </th>
                <td> [=cross-platform attachment|cross-platform=] </td>
                <td> [=client-side credential storage modality|Client-side storage=] </td>
                <td> [=Multi-factor capable=] </td>
            </tr>
            <tr>
                <th> <dfn>Passkey platform authenticator</dfn> </th>
                <td> [=platform attachment|platform=] ({{AuthenticatorTransport|transport}} = {{AuthenticatorTransport/internal}}) or [=cross-platform attachment|cross-platform=] ({{AuthenticatorTransport|transport}} = {{AuthenticatorTransport/hybrid}})</td>
                <td> [=client-side credential storage modality|Client-side storage=] </td>
                <td> [=Multi-factor capable=] </td>
            </tr>
        </tbody>
    </table>
    <figcaption>
        Definitions of names for some [=authenticator types=].
    </figcaption>
</figure>

A [=second-factor platform authenticator=] is convenient to use for re-authentication on the same [=client device=],
and can be used to add an extra layer of security both when initiating a new session and when resuming an existing session.
A [=second-factor roaming authenticator=] is more likely to be used
to authenticate on a particular [=client device=] for the first time,
or on a [=client device=] shared between multiple users.

[=Passkey platform authenticators=] and [=passkey roaming authenticators=]
enable passwordless [=multi-factor=] authentication.
In addition to the proof of possession of the [=credential private key=],
these authenticators support [=user verification=] as a second [=authentication factor=],
typically a PIN or [=biometric recognition=].
The [=authenticator=] can thus act as two kinds of [=authentication factor=],
which enables [=multi-factor=] authentication while eliminating the need to share a password with the [=[RP]=].
These authenticators also support [=discoverable credentials=], also called [=passkeys=],
meaning they also enable authentication flows where username input is not necessary.

The [=user-verifying platform authenticator=] class is largely obsoleted by the [=passkey platform authenticator=] class,
but the definition is still used by the {{PublicKeyCredential/isUserVerifyingPlatformAuthenticatorAvailable}} method.

The combinations not named in <a href="#table-authenticatorTypes">Table <span class="table-ref-previous"></span></a>
have less distinguished use cases:


- A [=roaming authenticator=] that is [=discoverable credential capable=] but not [=multi-factor capable=]
    can be used for [=single-factor=] authentication without a username,
    where the user is automatically identified by the [=user handle=]
    and possession of the [=credential private key=] is used as the only [=authentication factor=].
    This can be useful in some situations, but makes the user particularly vulnerable to theft of the [=authenticator=].
- A [=roaming authenticator=] that is [=multi-factor capable=] but not [=discoverable credential capable=]
    can be used for [=multi-factor=] authentication, but requires the user to be identified first
    which risks leaking [PII]; see [[#sctn-credential-id-privacy-leak]].

The following subsections define the aspects [=authenticator attachment modality=],
[=credential storage modality=] and [=authentication factor capability=] in more depth.


### <dfn>Authenticator Attachment Modality</dfn> ### {#sctn-authenticator-attachment-modality}

[=Clients=] can communicate with [=authenticators=] using a variety of mechanisms. For example, a [=client=] MAY use a
[=client device=]-specific API to communicate with an [=authenticator=] which is physically bound to a [=client device=]. On the other hand, a
[=client=] can use a variety of standardized cross-platform transport protocols such as Bluetooth (see [[#enum-transport]]) to discover
and communicate with [=cross-platform attachment|cross-platform attached=] [=authenticators=]. We refer to [=authenticators=] that
are part of the [=client device=] as <dfn>platform authenticators</dfn>, while those that are reachable via cross-platform
transport protocols are referred to as <dfn>roaming authenticators</dfn>.

- A [=platform authenticator=] is attached using a [=client device=]-specific transport, called <dfn>platform attachment</dfn>, and is usually not removable from the [=client
    device=]. A [=public key credential=] [=bound credential|bound=] to a [=platform authenticator=] is called a <dfn>platform credential</dfn>.

- A [=roaming authenticator=] is attached using cross-platform transports, called <dfn>cross-platform attachment</dfn>. Authenticators of this class are removable from, and
    can "roam" between, [=client devices=]. A [=public key credential=] [=bound credential|bound=] to a [=roaming authenticator=] is called a <dfn>roaming
    credential</dfn>.

Some [=platform authenticators=] could possibly also act as [=roaming authenticators=] depending on context. For example, a
[=platform authenticator=] integrated into a mobile device could make itself available as a [=roaming authenticator=] via
Bluetooth.
In this case [=clients=] running on the mobile device would recognise the authenticator as a [=platform authenticator=],
while [=clients=] running on a different [=client device=] and communicating with the same authenticator via Bluetooth
would recognize it as a [=roaming authenticator=].

The primary use case for [=platform authenticators=] is to register a particular [=client device=] as a "trusted device",
so the [=client device=] itself acts as a [=something you have=] [=authentication factor=] for future [=authentication=].
This gives the user the convenience benefit
of not needing a [=roaming authenticator=] for future [=authentication ceremonies=], e.g., the user will not have to dig around in
their pocket for their key fob or phone.

Use cases for [=roaming authenticators=] include:
[=authentication|authenticating=] on a new [=client device=] for the first time,
on rarely used [=client devices=], [=client devices=] shared between multiple users,
or [=client devices=] that do not include a [=platform authenticator=];
and when policy or preference dictates that the [=authenticator=] be kept separate from the [=client devices=] it is used with.
A [=roaming authenticator=] can also be used to hold
backup [=public key credential|credentials=] in case another [=authenticator=] is lost.


### Credential Storage Modality ### {#sctn-credential-storage-modality}

An [=authenticator=] can store a [=public key credential source=] in one of two ways:

 1. In persistent storage embedded in the [=authenticator=], [=client=] or [=client device=], e.g., in a secure element.
    This is a technical requirement for a [=client-side discoverable public key credential source=].

 1. By encrypting (i.e., wrapping) the [=public key credential source=]
    such that only this [=authenticator=] can decrypt (i.e., unwrap) it and letting the resulting
    ciphertext be the [=credential ID=] of the [=public key credential source=]. The [=credential ID=] is stored by the [=[RP]=]
    and returned to the [=authenticator=] via the {{PublicKeyCredentialRequestOptions/allowCredentials}} option of
    {{CredentialsContainer/get()}}, which allows the [=authenticator=] to decrypt and use the [=public key credential source=].

    This enables the [=authenticator=] to have unlimited credential storage capacity, since the encrypted
    [=public key credential sources=] are stored by the [=[RP]=] instead of by the [=authenticator=] - but it means that a
    [=credential=] stored in this way must be retrieved from the [=[RP]=] before the [=authenticator=] can use it.

Which of these storage strategies an [=authenticator=] supports defines the [=authenticator=]'s <dfn>credential storage
modality</dfn> as follows:

- An [=authenticator=] has the <dfn>client-side credential storage modality</dfn> if it supports [=client-side discoverable public key
    credential sources=]. An [=authenticator=] with [=client-side credential storage modality=] is also called <dfn>discoverable
    credential capable</dfn>.

- An [=authenticator=] has the <dfn>server-side credential storage modality</dfn> if it does not have the [=client-side credential storage
    modality=], i.e., it only supports storing [=public key credential sources=] as a ciphertext in the [=credential ID=].

Note that a [=discoverable credential capable=] [=authenticator=] MAY support both storage strategies. In this case, the [=authenticator=] MAY
at its discretion use different storage strategies for different [=public key credential|credentials=], though subject to the
{{AuthenticatorSelectionCriteria/residentKey}} and {{AuthenticatorSelectionCriteria/requireResidentKey}} options of
{{CredentialsContainer/create()}}.


### <dfn>Authentication Factor Capability</dfn> ### {#sctn-authentication-factor-capability}

There are three broad classes of [=authentication factors=] that can be used to prove an identity during an [=authentication
ceremony=]: [=something you have=], [=something you know=] and [=something you are=]. Examples include a physical key, a password,
and a fingerprint, respectively.

All [=[WAA]s=] belong to the [=something you have=] class, but an [=authenticator=] that supports [=user
verification=] can also act as one or two additional kinds of [=authentication factor=]. For example, if the [=authenticator=] can
verify a PIN, the PIN is [=something you know=], and a [=biometric authenticator=] can verify [=something you are=]. Therefore, an
[=authenticator=] that supports [=user verification=] is <dfn>multi-factor capable</dfn>. Conversely, an [=authenticator=] that is
not [=multi-factor capable=] is <dfn>single-factor capable</dfn>. Note that a single [=multi-factor capable=] [=authenticator=]
could support several modes of [=user verification=], meaning it could act as all three kinds of [=authentication factor=].

Although [=user verification=] is performed locally on the [=authenticator=] and not by the [=[RP]=], the [=authenticator=]
indicates if [=user verification=] was performed by setting the [=authData/flags/UV=] [=flag=] in the signed response returned to the [=[RP]=].
The [=[RP]=] can therefore use the [=authData/flags/UV=] [=flag=] to verify that additional [=authentication factors=] were used in a
[=registration=] or [=authentication ceremony=]. The authenticity of the [=authData/flags/UV=] [=flag=] can in turn be assessed by inspecting the
[=authenticator=]'s [=attestation statement=].


## <dfn>Authenticator Operations</dfn> ## {#sctn-authenticator-ops}

A [=[WAC]=] MUST connect to an authenticator in order to invoke any of the operations of that authenticator. This connection
defines an <dfn>authenticator session</dfn>. An authenticator must maintain isolation between sessions. It may do this by only allowing one
session to exist at any particular time, or by providing more complicated session management.

The following operations can be invoked by the client in an authenticator session.


### Lookup Credential Source by Credential ID Algorithm ### {#sctn-op-lookup-credsource-by-credid}

The result of <dfn for="credential id">looking up</dfn> a [=credential id=] |credentialId| in an [=authenticator=]
|authenticator| is the result of the following algorithm:
1. If |authenticator| can decrypt |credentialId| into a [=public key credential source=] |credSource|:
    1. Set |credSource|.[=public key credential source/id=] to |credentialId|.
    1. Return |credSource|.
1. [=map/For each=] [=public key credential source=] |credSource| of |authenticator|'s [=credentials map=]:
    1. If |credSource|.[=public key credential source/id=] is |credentialId|, return |credSource|.
1. Return `null`.


### The <dfn>authenticatorMakeCredential</dfn> Operation ### {#sctn-op-make-cred}

Before invoking this operation, the client MUST invoke the [=authenticatorCancel=] operation
in order to abort all other operations in progress in the [=authenticator session=].

This operation takes the following input parameters:

<!-- @@EDITOR-ANCHOR-01: KEEP THIS LIST SYNC'D WITH OTHER LOCATIONS WITH THIS TAG -->
: |hash|
:: The [=hash of the serialized client data=], provided by the client.
: |rpEntity|
:: The [=[RP]=]'s {{PublicKeyCredentialRpEntity}}.
: |userEntity|
:: The [=user account's=] {{PublicKeyCredentialUserEntity}}, containing the [=user handle=] given by the [=[RP]=].
: |requireResidentKey|
:: The [=effective resident key requirement for credential creation=], a Boolean value determined by the [=client=].
: |requireUserPresence|
:: The constant Boolean value [TRUE], or |FALSE| when <code>|options|.{{CredentialCreationOptions/mediation}}</code> is set to {{CredentialMediationRequirement/conditional}} and the user agent previously collected consent from the user.
: |requireUserVerification|
:: The [=effective user verification requirement for credential creation=], a Boolean value determined by the [=client=].
: |credTypesAndPubKeyAlgs|
:: A sequence of pairs of {{PublicKeyCredentialType}} and public key algorithms ({{COSEAlgorithmIdentifier}}) requested by the
    [=[RP]=]. This sequence is ordered from most preferred to least preferred. The [=authenticator=] makes a best-effort to create the most
    preferred credential that it can.
: |excludeCredentialDescriptorList|
:: An OPTIONAL list of {{PublicKeyCredentialDescriptor}} objects provided by the [=[RP]=] with the intention that, if any of
    these are known to the authenticator, it SHOULD NOT create a new credential. |excludeCredentialDescriptorList| contains a
    list of known credentials.
: |enterpriseAttestationPossible|
:: A Boolean value that indicates that individually-identifying attestation MAY be returned by the authenticator.
: |attestationFormats|
:: A sequence of strings that expresses the [=[RP]=]'s preference for attestation statement formats, from most to least preferable. If the [=authenticator=] returns [=attestation=], then it makes a best-effort attempt to use the most preferable format that it supports.
: |extensions|
:: A [=CBOR=] [=map=] from [=extension identifiers=] to their [=authenticator extension inputs=], created by the [=client=] based on
    the extensions requested by the [=[RP]=], if any.

When this operation is invoked, the [=authenticator=] MUST perform the following procedure:
1. Check if all the supplied parameters are syntactically well-formed and of the correct length. If not, return an error code
    equivalent to "{{UnknownError}}" and terminate the operation.
1. Check if at least one of the specified combinations of {{PublicKeyCredentialType}} and cryptographic parameters in
    |credTypesAndPubKeyAlgs| is supported.
    If not, return an error code equivalent to "{{NotSupportedError}}" and terminate the operation.

1. [=list/For each=] |descriptor| of |excludeCredentialDescriptorList|:

    1.  If [=credential id/looking up=] <code>|descriptor|.{{PublicKeyCredentialDescriptor/id}}</code> in this authenticator
        returns non-null, and the returned [=list/item=]'s [=RP ID=] and [=public key credential source/type=] match
        <code>|rpEntity|.{{PublicKeyCredentialRpEntity/id}}</code> and
        <code>|excludeCredentialDescriptorList|.{{PublicKeyCredentialDescriptor/type}}</code> respectively,
        then collect an [=authorization gesture=] confirming [=user
        consent=] for creating a new credential. The [=authorization gesture=] MUST include a [=test
        of user presence=]. If the user
        <dl class="switch">
            :   confirms consent to create a new credential
            ::  return an error code equivalent to "{{InvalidStateError}}" and terminate the operation.

            :   does not consent to create a new credential
            ::  return an error code equivalent to "{{NotAllowedError}}" and terminate the operation.
        </dl>

        Note: The purpose of this [=authorization gesture=] is not to proceed with creating a credential,
        but for privacy reasons to authorize disclosure of the fact that
        <code>|descriptor|.{{PublicKeyCredentialDescriptor/id}}</code> is [=bound credential|bound=] to this [=authenticator=].
        If the user consents, the [=client=] and [=[RP]=] can detect this and guide the user to use a different [=authenticator=].
        If the user does not consent,
        the [=authenticator=] does not reveal that <code>|descriptor|.{{PublicKeyCredentialDescriptor/id}}</code>
        is [=bound credential|bound=] to it,
        and responds as if the user simply declined consent to create a credential.

1. If |requireResidentKey| is [TRUE] and the authenticator cannot store a [=client-side discoverable public key credential source=],
    return an error code equivalent to "{{ConstraintError}}" and terminate the operation.
1. If |requireUserVerification| is [TRUE] and the authenticator cannot perform [=user verification=], return an error code
    equivalent to "{{ConstraintError}}" and terminate the operation.

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list :-/
-->
    <li id='op-makecred-step-user-consent'>
        Collect an [=authorization gesture=] confirming [=user consent=] for creating a new credential.
        The prompt for the [=authorization gesture=] is shown by the
        authenticator if it has its own output capability, or by the user agent otherwise. The prompt SHOULD display
        <code>|rpEntity|.{{PublicKeyCredentialRpEntity/id}}</code>, <code>|rpEntity|.{{PublicKeyCredentialEntity/name}}</code>,
        <code>|userEntity|.{{PublicKeyCredentialEntity/name}}</code> and
        <code>|userEntity|.{{PublicKeyCredentialUserEntity/displayName}}</code>, if possible.

        If |requireUserVerification| is [TRUE], the [=authorization gesture=] MUST include [=user verification=].

        If |requireUserPresence| is [TRUE], the [=authorization gesture=] MUST include a [=test of user presence=].

        If the user does not [=user consent|consent=] or if [=user verification=] fails, return an error code equivalent to
        "{{NotAllowedError}}" and terminate the operation.
    </li>

1. Once the [=authorization gesture=] has been completed and [=user consent=] has been obtained, generate a new credential object:
    1. Let (|publicKey|, |privateKey|) be a new pair of cryptographic keys using the combination of {{PublicKeyCredentialType}}
        and cryptographic parameters represented by the first [=list/item=] in |credTypesAndPubKeyAlgs| that is supported by
        this authenticator.
    1. Let |userHandle| be <code>|userEntity|.{{PublicKeyCredentialUserEntity/id}}</code>.
    1. Let |credentialSource| be a new [=public key credential source=] with the fields:
        <dl link-for="public key credential source">
            : [=type=]
            :: {{PublicKeyCredentialType/public-key}}.
            : [=privateKey=]
            :: |privateKey|
            : [=rpId=]
            :: <code>|rpEntity|.{{PublicKeyCredentialRpEntity/id}}</code>
            : [=userHandle=]
            :: |userHandle|
            : [=otherUI=]
            :: Any other information the authenticator chooses to include.
        </dl>
    1. If |requireResidentKey| is [TRUE] or the authenticator chooses to create a [=client-side discoverable public key credential source=]:
        1. Let |credentialId| be a new [=credential id=].
        1. Set |credentialSource|.[=public key credential source/id=] to |credentialId|.
        1. Let |credentials| be this authenticator's [=credentials map=].
        1. [=map/Set=] |credentials|[(<code>|rpEntity|.{{PublicKeyCredentialRpEntity/id}}</code>, |userHandle|)] to |credentialSource|.
    1. Otherwise:
        1. Let |credentialId| be the result of serializing and encrypting |credentialSource| so that only this authenticator can
            decrypt it.
1. If any error occurred while creating the new credential object, return an error code equivalent to "{{UnknownError}}" and
    terminate the operation.
1. Let |processedExtensions| be the result of [=authenticator extension processing=] [=map/for each=] supported [=extension
    identifier=] → [=authenticator extension input=] in |extensions|.
1. If the [=authenticator=]:
    <dl class="switch">
        : is a U2F device
        :: let the [=signature counter=] value for the new credential be zero. (U2F devices may support signature counters but do not return a counter when making a credential. See [[FIDO-U2F-Message-Formats]].)

        : supports a global [=signature counter=]
        ::  Use the global [=signature counter=]'s actual value when generating
              [=authenticator data=].

        : supports a per credential [=signature counter=]
        :: allocate the counter, associate it with the new credential, and initialize the counter value as zero.

        : does not support a [=signature counter=]
        :: let the [=signature counter=] value for the new credential be constant at zero.
    </dl>

1. Let |attestedCredentialData| be the [=attested credential data=] byte array including the |credentialId| and |publicKey|.
1. Let |attestationFormat| be the first supported [=attestation statement format identifier=] from |attestationFormats|, taking into account |enterpriseAttestationPossible|.
    If |attestationFormats| contains no supported value, then let |attestationFormat| be the [=attestation statement format identifier=] most preferred by this authenticator.
1. Let |authenticatorData| [=perform the following steps to generate an authenticator data structure|be the byte array=] specified in [[#sctn-authenticator-data]], including |attestedCredentialData| as the
    <code>[=attestedCredentialData=]</code> and |processedExtensions|, if any, as the
    <code>[=authData/extensions=]</code>.
1. Create an [=attestation object=] for the new credential using the procedure specified in
    [[#sctn-generating-an-attestation-object]], the [=attestation statement format=] |attestationFormat|, and the values |authenticatorData|
    and |hash|, as well as {{enterprise|taking into account}} the value of |enterpriseAttestationPossible|. For more details on attestation, see [[#sctn-attestation]].

On successful completion of this operation, the authenticator returns the [=attestation object=] to the client.


### The <dfn>authenticatorGetAssertion</dfn> Operation ### {#sctn-op-get-assertion}

Before invoking this operation, the client MUST invoke the [=authenticatorCancel=] operation
in order to abort all other operations in progress in the [=authenticator session=].

This operation takes the following input parameters:

: |rpId|
:: The caller's [=RP ID=], as <a href='#GetAssn-DetermineRpId'>determined</a> by the user agent and the client.
: |hash|
:: The [=hash of the serialized client data=], provided by the client.
: |allowCredentialDescriptorList|
:: An OPTIONAL [=list=] of {{PublicKeyCredentialDescriptor}}s describing credentials acceptable to the [=[RP]=] (possibly filtered
    by the client), if any.
: |requireUserPresence|
:: The constant Boolean value [TRUE].
    It is included here as a pseudo-parameter to simplify applying this abstract authenticator model to implementations that may
    wish to make a [=test of user presence=] optional although WebAuthn does not.
: |requireUserVerification|
:: The [=effective user verification requirement for assertion=], a Boolean value provided by the client.
: |extensions|
:: A [=CBOR=] [=map=] from [=extension identifiers=] to their [=authenticator extension inputs=], created by the client based on
    the extensions requested by the [=[RP]=], if any.

When this method is invoked, the [=authenticator=] MUST perform the following procedure:

1. Check if all the supplied parameters are syntactically well-formed and of the correct length. If not, return an error code
    equivalent to "{{UnknownError}}" and terminate the operation.
1. Let |credentialOptions| be a new empty [=set=] of [=public key credential sources=].
1. If |allowCredentialDescriptorList| was supplied, then [=list/for each=] |descriptor| of |allowCredentialDescriptorList|:
    1. Let |credSource| be the result of [=looking up=] <code>|descriptor|.{{PublicKeyCredentialDescriptor/id}}</code> in this
        authenticator.
    1. If |credSource| is not `null`, [=set/append=] it to |credentialOptions|.
1. Otherwise (|allowCredentialDescriptorList| was not supplied), [=map/for each=] <var ignore>key</var> → |credSource| of this
    authenticator's [=credentials map=], [=set/append=] |credSource| to |credentialOptions|.
1. [=list/Remove=] any items from |credentialOptions| whose [=public key credential source/rpId=] is not equal to
    |rpId|.
1. If |credentialOptions| is now empty, return an error code equivalent to "{{NotAllowedError}}" and terminate the operation.

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list -->
    <li id="authenticatorGetAssertion-prompt-select-credential">
        Prompt the user to select a [=public key credential source=] |selectedCredential| from |credentialOptions|.
        Collect an [=authorization gesture=] confirming [=user consent=] for using |selectedCredential|.
        The prompt for the [=authorization gesture=] may be shown
        by the [=authenticator=] if it has its own output capability, or by the user agent otherwise.

        If |requireUserVerification| is [TRUE], the [=authorization gesture=] MUST include [=user verification=].

        If |requireUserPresence| is [TRUE], the [=authorization gesture=] MUST include a
            [=test of user presence=].

        If the user does not [=user consent|consent=], return an error code equivalent to
        "{{NotAllowedError}}" and terminate the operation.
    </li>

1. Let |processedExtensions| be the result of [=authenticator extension processing=] [=map/for each=] supported [=extension
    identifier=] → [=authenticator extension input=] in |extensions|.
1. Increment the credential associated
    [=signature counter=] or the global [=signature counter=] value, depending on
    which approach is implemented by the [=authenticator=], by some positive value.
    If the [=authenticator=] does not implement a [=signature counter=], let the [=signature counter=] value remain constant at
    zero.
1. Let |authenticatorData| [=perform the following steps to generate an authenticator data structure|be the byte array=]
    specified in [[#sctn-authenticator-data]] including |processedExtensions|, if any, as
    the <code>[=authData/extensions=]</code> and excluding <code>[=attestedCredentialData=]</code>.
1. Let |signature| be the [=assertion signature=] of the concatenation <code>|authenticatorData| || |hash|</code> using the
    [=public key credential source/privateKey=] of |selectedCredential| as shown in <a href="#fig-signature">Figure <span class="figure-num-following"></span></a>, below. A simple,
    undelimited
    concatenation is safe to use here because the [=authenticator data=] describes its own length. The [=hash of the serialized
    client data=] (which potentially has a variable length) is always the last element.

    <figure id="fig-signature">
        <img no-autosize src="images/fido-signature-formats-figure2.svg">
        <figcaption>Generating an [=assertion signature=].</figcaption>
    </figure>

1. If any error occurred while generating the [=assertion signature=], return an error code equivalent to "{{UnknownError}}" and
    terminate the operation.

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list :-/
-->
    <li id='authenticatorGetAssertion-return-values'>
        Return to the user agent:
            - |selectedCredential|.[=public key credential source/id=], if either a list of credentials
                (i.e., |allowCredentialDescriptorList|) of length 2 or greater was
                supplied by the client, or no such list was supplied.

                    Note: If, within |allowCredentialDescriptorList|, the client supplied exactly one credential and it was successfully employed, then its
                        [=credential ID=] is not returned since the client already knows it. This saves transmitting these bytes over
                        what may be a constrained connection in what is likely a common case.

            - |authenticatorData|
            - |signature|
            - |selectedCredential|.[=public key credential source/userHandle=]

                    Note: In cases where |allowCredentialDescriptorList| was supplied the returned
                    [=public key credential source/userHandle=] value may be `null`, see: [=assertionCreationData/userHandleResult=].
    </li>

If the [=authenticator=] cannot find any [=public key credential|credential=] corresponding to the specified [=[RP]=] that
matches the specified criteria, it terminates the operation and returns an error.


### The <dfn>authenticatorCancel</dfn> Operation ### {#sctn-op-cancel}

This operation takes no input parameters and returns no result.

When this operation is invoked by the client in an [=authenticator session=], it has the effect of terminating any
[=authenticatorMakeCredential=] or [=authenticatorGetAssertion=] operation currently in progress in that authenticator
session. The authenticator stops prompting for, or accepting, any user input related to authorizing the canceled operation. The
client ignores any further responses from the authenticator for the canceled operation.

This operation is ignored if it is invoked in an [=authenticator session=] which does not have an [=authenticatorMakeCredential=]
or [=authenticatorGetAssertion=] operation currently in progress.


### The <dfn>silentCredentialDiscovery</dfn> operation ### {#sctn-op-silent-discovery}

This is an OPTIONAL operation authenticators MAY support to enable {{CredentialMediationRequirement/conditional}}
[=user mediation=].

It takes the following input parameter:

: |rpId|
:: The caller's [=RP ID=], as <a href='#GetAssn-DetermineRpId'>determined</a> by the [=client=].

When this operation is invoked, the [=authenticator=] MUST perform the following procedure:

1. Let |collectedDiscoverableCredentialMetadata| be a new [=list=] whose [=list/items=] are
    <dfn>DiscoverableCredentialMetadata</dfn> [=structs=] with the following [=struct/items=]:

    <dl dfn-for="DiscoverableCredentialMetadata">
        :   <dfn>type</dfn>
        ::  A {{PublicKeyCredentialType}}.

        :   <dfn>id</dfn>
        ::  A [=Credential ID=].

        :   rpId
        ::  A [=Relying Party Identifier=].

        :   userHandle
        ::  A [=user handle=].

        :   <dfn>otherUI</dfn>
        ::  Other information used by the [=authenticator=] to inform its UI.
    </dl>

1. [=map/For each=] [=public key credential source=] |credSource| of |authenticator|'s [=credentials map=]:

    1. If |credSource| is not a [=client-side discoverable credential=], [=iteration/continue=].

    1. If |credSource|.[=public key credential source/rpId=] is not |rpId|, [=iteration/continue=].

    1. Let |discoveredCredentialMetadata| be a new [=DiscoverableCredentialMetadata=] [=struct=] whose [=struct/items=]
        are copies of |credSource|'s [=public key credential source/type=], [=public key credential source/id=],
        [=public key credential source/rpId=], [=public key credential source/userHandle=] and
        [=public key credential source/otherUI=].

    1. [=list/Append=] |discoveredCredentialMetadata| to |collectedDiscoverableCredentialMetadata|.

1. Return |collectedDiscoverableCredentialMetadata|.


## String Handling ## {#sctn-strings}

Authenticators may be required to store arbitrary strings chosen by a [=[RP]=], for example the {{PublicKeyCredentialEntity/name}} and {{PublicKeyCredentialUserEntity/displayName}} in a {{PublicKeyCredentialUserEntity}}. This section discusses some practical consequences of handling arbitrary strings that may be presented to humans.

### String Truncation ### {#sctn-strings-truncation}

Each arbitrary string in the API will have some accommodation for the potentially limited resources available to an [=authenticator=].
When the chosen accommodation is string truncation, care needs to be taken to not corrupt the string value.

For example, truncation based on Unicode code points alone may cause a [=grapheme cluster=] to be truncated.
This could make the grapheme cluster render as a different glyph,
potentially changing the meaning of the string, instead of removing the glyph entirely.
For example, <a href="#fig-stringTruncation">figure <span class="figure-num-following"></span></a>
shows the end of a UTF-8 encoded string whose encoding is 65 bytes long.
If truncating to 64 bytes then the final 0x88 byte is removed first to satisfy the size limit.
Since that leaves a partial UTF-8 code point, the remainder of that code point must also be removed.
Since that leaves a partial [=grapheme cluster=], the remainder of that cluster should also be removed.

<figure id="fig-stringTruncation">
    <img no-autosize src="images/string-truncation.svg">
    <figcaption>The end of a UTF-8 encoded string showing the positions of different truncation boundaries.</figcaption>
</figure>

The responsibility for handling these concerns falls primarily on the [=client=],
to avoid burdening [=authenticators=] with understanding character encodings and Unicode character properties.
The following subsections define requirements for how clients and authenticators,
respectively, may perform string truncation.


#### String Truncation by Clients #### {#sctn-strings-truncation-client}

When a [=[WAC]=] truncates a string,
the truncation behaviour observable by the [=[RP]=] MUST satisfy the following requirements:

Choose a size limit equal to or greater than the specified minimum supported length.
The string MAY be truncated so that its length in bytes in the UTF-8 character encoding satisfies that limit.
This truncation MUST respect UTF-8 code point boundaries, and SHOULD respect [=grapheme cluster=] boundaries [[UAX29]].
The resulting truncated value MAY be shorter than the chosen size limit
but MUST NOT be shorter than the longest prefix substring that satisfies the size limit and ends on a [=grapheme cluster=] boundary.

The client MAY let the [=authenticator=] perform the truncation if it satisfies these requirements;
otherwise the client MUST perform the truncation before relaying the string value to the authenticator.

In addition to the above, truncating on byte boundaries alone causes a known issue that user agents should be aware of: if the authenticator is using [[!FIDO-CTAP]] then future messages from the authenticator may contain invalid CBOR since the value is typed as a CBOR string and thus is required to be valid UTF-8. Thus, when dealing with [=authenticators=], user agents SHOULD:

1. Ensure that any strings sent to authenticators are validly encoded.
1. Handle the case where strings have been truncated resulting in an invalid encoding. For example, any partial code point at the end may be dropped or replaced with [U+FFFD](http://unicode.org/cldr/utility/character.jsp?a=FFFD).


#### String Truncation by Authenticators #### {#sctn-strings-truncation-authenticator}

Because a [=[WAA]=] may be implemented in a constrained environment,
the requirements on authenticators are relaxed compared to those for [=clients=].

When a [=[WAA]=] truncates a string,
the truncation behaviour MUST satisfy the following requirements:

Choose a size limit equal to or greater than the specified minimum supported length.
The string MAY be truncated so that its length in bytes in the UTF-8 character encoding satisfies that limit.
This truncation SHOULD respect UTF-8 code point boundaries, and MAY respect [=grapheme cluster=] boundaries [[UAX29]].
The resulting truncated value MAY be shorter than the chosen size limit
but MUST NOT be shorter than the longest prefix substring that satisfies the size limit and ends on a [=grapheme cluster=] boundary.


### Language and Direction Encoding ### {#sctn-strings-langdir}

In order to be correctly displayed in context, the language and base direction of a string [may be required](https://www.w3.org/TR/string-meta/#why-is-this-important). Strings in this API may have to be written to fixed-function [=authenticators=] and then later read back and displayed on a different platform.

For compatibility with existing fixed-function [=authenticators=] without support for dedicated language and direction metadata fields,
Web Authentication Level 2 included provisions for embedding such metadata in the string itself to ensure that it is transported atomically.
This encoding is NOT RECOMMENDED; [=clients=] and [=authenticators=] MAY ignore such encoding in new values.
[=Clients=] and [=authenticators=] MAY detect and process language and direction metadata encoded in existing strings
as described in [[webauthn-2-20210408#sctn-strings-langdir|Web Authentication Level 2 §6.4.2. Language and Direction Encoding]].

Instead, a future version of the [=Web Authentication API=] may provide dedicated language and direction metadata fields.


## Attestation ## {#sctn-attestation}

[=Authenticators=] SHOULD also provide some form of [=attestation=], if possible.
If an authenticator does, the basic requirement is that the [=authenticator=] can
produce, for each [=credential public key=], an [=attestation statement=] verifiable by the [=[WRP]=]. Typically, this
[=attestation statement=] contains a signature by an [=attestation private key=] over the attested [=credential public key=] and
a challenge, as well as a certificate or similar data providing provenance information for the [=attestation public key=],
enabling the [=[RP]=] to make a trust decision. However, if an [=attestation key pair=] is not available, then the authenticator
MAY either perform [=self attestation=] of the [=credential public key=] with the corresponding [=credential private key=],
or otherwise perform [=None|no attestation=]. All this information is returned by [=authenticators=] any time a new
[=public key credential=] is generated, in the overall form of an <dfn>attestation object</dfn>. The relationship of the
[=attestation object=] with [=authenticator data=] (containing [=attested credential data=]) and the [=attestation statement=]
is illustrated in <a href="#fig-attStructs">figure <span class="figure-num-following"></span></a>, below.

If an [=authenticator=] employs [=self attestation=] or [=None|no attestation=], then no provenance information is provided
for the [=[RP]=] to base a trust decision on.
In these cases, the [=authenticator=] provides no guarantees about its operation to the [=[RP]=].

<figure id="fig-attStructs">
    <img no-autosize src="images/fido-attestation-structures.svg">
    <figcaption>[=Attestation object=] layout illustrating the included [=authenticator data=] (containing [=attested credential
    data=]) and the [=attestation statement=].</figcaption>
</figure>
<div class="note">
    <span class="marker">Note:</span>
    This figure illustrates only the `packed` [=attestation statement format=]. Several additional [=attestation statement
    formats=] are defined in [[#sctn-defined-attestation-formats]].
</div>

An important component of the [=attestation object=] is the <dfn>attestation statement</dfn>. This is a specific type of signed
data object, containing statements about a [=public key credential=] itself and the [=authenticator=] that created it. It
contains an [=attestation signature=] created using the key of the attesting authority (except for the case of [=self
attestation=], when it is created using the [=credential private key=]). In order to correctly interpret an [=attestation
statement=], a [=[RP]=] needs to understand these two aspects of [=attestation=]:

1. The <dfn>attestation statement format</dfn> is the manner in which the signature is represented and the various contextual
    bindings are incorporated into the attestation statement by the [=authenticator=]. In other words, this defines the
    syntax of the statement. Various existing components and OS platforms (such as TPMs and the Android OS) have previously defined
    [=attestation statement formats=]. This specification supports a variety of such formats in an extensible way, as defined in
    [[#sctn-attestation-formats]]. The formats themselves are identified by strings, as described in [[#sctn-attstn-fmt-ids]].

2. The <dfn>attestation type</dfn> defines the semantics of [=attestation statements=] and their underlying trust models.
    Specifically, it defines how a [=[RP]=] establishes trust in a particular [=attestation statement=], after verifying that it
    is cryptographically valid. This specification supports a number of [=attestation types=], as described in
    [[#sctn-attestation-types]].

In general, there is no simple mapping between [=attestation statement formats=] and [=attestation types=]. For example, the
"packed" [=attestation statement format=] defined in [[#sctn-packed-attestation]] can be used in conjunction with all [=attestation
types=], while other formats and types have more limited applicability.

The privacy, security and operational characteristics of [=attestation=] depend on:
- The [=attestation type=], which determines the trust model,
- The [=attestation statement format=], which MAY constrain the strength of the [=attestation=] by limiting what can be
    expressed in an [=attestation statement=], and
- The characteristics of the individual [=authenticator=], such as its construction, whether part or all of it runs in a secure
    operating environment, and so on.

The [=attestation type=] and [=attestation statement format=] is chosen by the [=authenticator=];
[=[RPS]=] can only signal their preferences by setting the {{PublicKeyCredentialCreationOptions/attestation}} and {{PublicKeyCredentialCreationOptions/attestationFormats}} parameters.

It is expected that most [=authenticators=] will support a small number of [=attestation types=] and [=attestation statement
formats=], while [=[RPS]=] will decide what [=attestation types=] are acceptable to them by policy. [=[RPS]=] will also need to
understand the characteristics of the [=authenticators=] that they trust, based on information they have about these
[=authenticators=]. For example, the FIDO Metadata Service [[FIDOMetadataService]] provides one way to access such information.

### Attested Credential Data ### {#sctn-attested-credential-data}

<dfn>Attested credential data</dfn> is a variable-length byte array added to the [=authenticator data=] when generating an [=attestation
object=] for a credential. Its format is shown in <a href="#table-attestedCredentialData">Table <span class="table-ref-following"></span></a>.

<figure id="table-attestedCredentialData" class="table">
    <table class="complex data longlastcol" dfn-for="authData/attestedCredentialData">
        <tr>
            <th>Name</th>
            <th>Length (in bytes)</th>
            <th>Description</th>
        </tr>
        <tr>
            <td><dfn>aaguid</dfn></td>
            <td>16</td>
            <td>The [=/AAGUID=] of the authenticator.</td>
        </tr>
        <tr>
            <td><dfn>credentialIdLength</dfn></td>
            <td>2</td>
            <td>Byte length <strong>L</strong> of [=credentialId=], 16-bit unsigned big-endian integer. Value MUST be &le; 1023.</td>
        </tr>
        <tr>
            <td><dfn>credentialId</dfn></td>
            <td>L</td>
            <td>[=Credential ID=]</td>
        </tr>
        <tr>
            <td><dfn>credentialPublicKey</dfn></td>
            <td>variable</td>
            <td>
                The [=credential public key=] encoded in COSE_Key format,
                as defined in [=Section 7=] of [[!RFC9052]], using the [=CTAP2 canonical CBOR encoding form=].
                The COSE_Key-encoded [=credential public key=] MUST contain the "alg" parameter and MUST NOT
                contain any other OPTIONAL parameters. The "alg" parameter MUST contain a {{COSEAlgorithmIdentifier}} value.
                The encoded [=credential public key=] MUST also contain any additional REQUIRED parameters stipulated by the
                relevant key type specification, i.e., REQUIRED for the key type "kty" and algorithm "alg"
                (see [=RFC9053/Section 2=] of [[!RFC9053]]).
            </td>
        </tr>
    </table>
    <figcaption>
        [=Attested credential data=] layout. The names in the Name column are only for reference within this document, and are not
        present in the actual representation of the [=attested credential data=].
    </figcaption>
</figure>

#### Examples of `credentialPublicKey` Values Encoded in COSE_Key Format #### {#sctn-encoded-credPubKey-examples}

This section provides examples of COSE_Key-encoded Elliptic Curve and RSA public keys for the ES256, PS256, and RS256
signature algorithms. These examples adhere to the rules defined above for the [=credentialPublicKey=] value, and are presented in CDDL [[!RFC8610]] for clarity.

[=Section 7=] of [[!RFC9052]] defines the general framework for all COSE_Key-encoded keys.
Specific key types for specific algorithms are defined in [[!RFC9053]] as well as in other specifications,
as noted below.

Below is an example of a COSE_Key-encoded Elliptic Curve public key in EC2 format (see [=Section 7.1=] of [[!RFC9053]]),
on the P-256 curve, to be used with the ES256 signature
algorithm (ECDSA w/ SHA-256, see [=Section 2.1=] of [[!RFC9053]]):

<xmp class="example" highlight="cddl">
  {
    1:   2,  ; kty: EC2 key type
    3:  -7,  ; alg: ES256 signature algorithm
   -1:   1,  ; crv: P-256 curve
   -2:   x,  ; x-coordinate as byte string 32 bytes in length
             ; e.g., in hex: 65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d
   -3:   y   ; y-coordinate as byte string 32 bytes in length
             ; e.g., in hex: 1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c
  }
</xmp>

Below is the above Elliptic Curve public key encoded in the [=CTAP2 canonical CBOR encoding form=], whitespace and line breaks
are included here for clarity and to match the CDDL [[!RFC8610]] presentation above:

<xmp class="example">
  A5
     01  02

     03  26

     20  01

     21  58 20   65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d

     22  58 20   1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c
</xmp>


Below is an example of a COSE_Key-encoded 2048-bit RSA public key (see [[RFC8230]] [=Section 4=],
to be used with the PS256 signature algorithm
(RSASSA-PSS with SHA-256, see [=RFC8230/Section 2=] of [[RFC8230]]:

<xmp class="example" highlight="cddl">
  {
    1:   3,  ; kty: RSA key type
    3: -37,  ; alg: PS256
   -1:   n,  ; n:   RSA modulus n byte string 256 bytes in length
             ;      e.g., in hex (middle bytes elided for brevity): DB5F651550...6DC6548ACC3
   -2:   e   ; e:   RSA public exponent e byte string 3 bytes in length
             ;      e.g., in hex: 010001
  }
</xmp>

Below is an example of the same COSE_Key-encoded RSA public key as above,
to be used with the RS256 signature algorithm (RSASSA-PKCS1-v1_5 with SHA-256):

<xmp class="example" highlight="cddl">
  {
    1:   3,  ; kty: RSA key type
    3:-257,  ; alg: RS256
   -1:   n,  ; n:   RSA modulus n byte string 256 bytes in length
             ;      e.g., in hex (middle bytes elided for brevity): DB5F651550...6DC6548ACC3
   -2:   e   ; e:   RSA public exponent e byte string 3 bytes in length
             ;      e.g., in hex: 010001
  }
</xmp>


### Attestation Statement Formats ### {#sctn-attestation-formats}

As described above, an [=attestation statement format=] is a data format which represents a cryptographic signature by an
[=authenticator=] over a set of contextual bindings. Each [=attestation statement format=] MUST be defined using the following
template:

- <strong>[=Attestation statement format identifier=]:</strong>

- <strong>Supported [=attestation types=]:</strong>

- <strong>Syntax:</strong>
    The syntax of an [=attestation statement=] produced in this format, defined using CDDL [[!RFC8610]] for the extension point
    `$$attStmtType` defined in [[#sctn-generating-an-attestation-object]].

- <dfn>Signing procedure</dfn>:
    The [=signing procedure=] for computing an [=attestation statement=] in this [=attestation statement format|format=] given
    the [=public key credential=] to be attested, the [=authenticator data=] structure containing the <dfn>authenticator data
    for the attestation</dfn>, and the [=hash of the serialized client data=].

- <dfn>Verification procedure</dfn>:
    The procedure for verifying an [=attestation statement=], which takes the following <dfn>verification procedure inputs</dfn>:
    - |attStmt|: The [=attestation statement=] structure
    - |authenticatorData|: The  <dfn>[=authenticator data=] claimed to have been used for the attestation</dfn>
    - |clientDataHash|: The [=hash of the serialized client data=]

    The procedure returns either:
    - An error indicating that the attestation is invalid, or
    - An implementation-specific value representing the [=attestation type=], and the [=attestation trust path|trust path=]. This <dfn>attestation trust path</dfn> is either
        empty (in case of [=self attestation=]), or a set of X.509 certificates.

The initial list of specified [=attestation statement formats=] is in [[#sctn-defined-attestation-formats]].


<!-- Editors Note: differentiating section IDs from non-section IDs is useful because at times we need to seperately reference
     different things having the same nominal name, eg attestation-types-the-section, and attestation-types-the-definition -->
### Attestation Types ### {#sctn-attestation-types}

WebAuthn supports several [=attestation types=], defining the semantics of [=attestation statements=] and their underlying trust
models:

Note: This specification does not define any data structures explicitly expressing the [=attestation types=] employed by
[=authenticators=]. [=[RPS]=] engaging in [=attestation statement=] [=verification procedure|verification=] &mdash; i.e., when
calling {{CredentialsContainer/create()|navigator.credentials.create()}} they select an [=attestation conveyance=] other than
{{AttestationConveyancePreference/none}} and verify the received [=attestation statement=] &mdash; will determine the employed
[=attestation type=] as a part of [=verification procedure|verification=]. See the "Verification procedure" subsections of
[[#sctn-defined-attestation-formats]]. See also [[#sctn-attestation-privacy]]. For all [=attestation types=] defined in this
section other than [=self attestation|Self=] and [=None=], [=[RP]=] [=verification procedure|verification=] is followed by
matching the [=attestation trust path|trust path=] to an acceptable root certificate per [step 23](#reg-ceremony-assess-trust)
of [[#sctn-registering-a-new-credential]].
Differentiating these [=attestation types=] becomes useful primarily as a means for determining if the [=attestation=] is acceptable
under [=[RP]=] policy.

: <dfn>Basic Attestation</dfn> (<dfn>Basic</dfn>)
:: In the case of basic attestation [[UAFProtocol]], the authenticator's [=attestation key pair=] is specific to an
    authenticator "model", i.e., a "batch" of authenticators.  Thus, authenticators of the same, or similar, model often share the same [=attestation key pair=]. See
    [[#sctn-attestation-privacy]] for further information.

    [=Basic attestation=] is also referred to as <dfn>batch attestation</dfn>.

: <dfn>Self Attestation</dfn> (<dfn>Self</dfn>)
:: In the case of [=self attestation=], also known as surrogate basic attestation [[UAFProtocol]], the Authenticator does not have
    any specific [=attestation key pair=]. Instead it uses the [=credential private key=] to create the [=attestation signature=].
    Authenticators without meaningful protection measures for an [=attestation private key=] typically use this attestation type.

: <dfn>Attestation CA</dfn> (<dfn>AttCA</dfn>)
:: In this case, an [=authenticator=] is based on a Trusted Platform Module (TPM) and holds an authenticator-specific
    "endorsement key" (EK). This key is used to securely communicate with a trusted third party, the [=Attestation CA=]
    [[!TCG-CMCProfile-AIKCertEnroll]] (formerly known as a "Privacy CA"). The [=authenticator=] can generate multiple
    attestation identity key pairs (AIK) and requests an [=Attestation CA=] to issue an AIK certificate
    for each. Using this approach, such an [=authenticator=] can limit the exposure of the EK (which is a global correlation
    handle) to Attestation CA(s). AIKs can be requested for each [=authenticator=]-generated [=public key credential=]
    individually, and conveyed to [=[RPS]=] as [=attestation certificates=].

    Note: This concept typically leads to multiple attestation certificates. The attestation certificate requested most recently
        is called "active".

: <dfn>Anonymization CA</dfn> (<dfn>AnonCA</dfn>)
:: In this case, the [=authenticator=] uses an [=Anonymization CA=] which dynamically generates per-[=credential=] [=attestation certificates=] such that the [=attestation statements=] presented to [=[RPS]=] do not provide uniquely identifiable information, e.g., that might be used for tracking purposes.

    Note: [=Attestation statements=] conveying [=attestations=] of [=attestation type|type=] [=AttCA=] or [=AnonCA=] use the same data structure
        as those of [=attestation type|type=] [=Basic=], so the three attestation types
        are, in general, distinguishable only with externally provided knowledge regarding the contents of the [=attestation
        certificates=] conveyed in the [=attestation statement=].

: No attestation statement (<dfn>None</dfn>)
:: In this case, no attestation information is available. See also [[#sctn-none-attestation]].

### Generating an Attestation Object ### {#sctn-generating-an-attestation-object}

To generate an [=attestation object=] (see: [Figure 6](#fig-attStructs)) given:

: |attestationFormat|
:: An [=attestation statement format=].
: |authData|
:: A byte array containing [=authenticator data=].
: |hash|
:: The [=hash of the serialized client data=].

the [=authenticator=] MUST:

1. Let <var ignore>attStmt</var> be the result of running |attestationFormat|'s [=signing procedure=] given |authData| and
    |hash|.
1. Let <var ignore>fmt</var> be |attestationFormat|'s [=attestation statement format identifier=]
1. Return the [=attestation object=] as a CBOR map with the following syntax, filled in with variables initialized by this
    algorithm:

    ```
    attObj = {
        authData: bytes,

        ; Each choice in $$attStmtType defines the fmt value and attStmt structure
        $$attStmtType
    } .within attStmtTemplate

    attStmtTemplate = {
        authData: bytes,
        fmt: text,
        attStmt: (
          { * tstr => any } ; Map is filled in by each concrete attStmtType
          //
          [ * any ]         ; attStmt may also be an array
        )
    }
    ```

### Signature Formats for Packed Attestation, FIDO U2F Attestation, and Assertion Signatures ### {#sctn-signature-attestation-types}
    - For COSEAlgorithmIdentifier -7 (ES256),  and other ECDSA-based algorithms, the
        `sig` value MUST be encoded as an ASN.1 DER Ecdsa-Sig-Value, as defined in [[RFC3279]] section 2.2.3.

        <!-- Example generated using https://github.com/w3c/webauthn/blob/96cc62b627f0b17114931e1bbc546f376f372c5d/test-vectors/webauthn-test-vectors.py#L1004-L1010 with seed 'none.ES256.442295' (442295 is the lowest value that generates a 33+30-byte signature, 2524 is the lowest that generates a 33+31-byte signature) -->
        ```
        Example:
        Note: Encoding lengths vary with INTEGER magnitude and curve size.
        30 43                                ; SEQUENCE (67 Bytes)
            02 21                            ; INTEGER (33 Bytes)
            | 00 89 90 95 04 e1 4f 1e 29 db a8 15 8f a7 c3 87
            | e8 88 ff be 07 d8 24 bb 21 43 20 55 06 ab 15 9c
            | 3e
            02 1e                            ; INTEGER (30 Bytes)
            | 56 55 4f b5 81 9b 12 84 5e 85 be 2f 78 37 1c f3
            | cb 95 e3 87 f4 51 cb 36 2b 94 78 d1 83 d2
        ```

        Note: As CTAP1/U2F [=authenticators=] are already producing signatures values in this format, CTAP2
        [=authenticators=] will also produce signatures values in the same format, for consistency reasons.

    It is RECOMMENDED that any new attestation formats defined not use ASN.1 encodings,
    but instead represent signatures as equivalent fixed-length byte arrays without internal structure,
    using the same representations as used by COSE signatures as defined in [[!RFC9053]] and [[!RFC8230]].

    The below signature format definitions satisfy this requirement and serve as examples for deriving the same for other signature algorithms not explicitly mentioned here:

    - For COSEAlgorithmIdentifier -257 (RS256), `sig` MUST contain the signature generated using the
        RSASSA-PKCS1-v1_5 signature scheme defined in Section 8.2.1 of [[RFC8017]] with SHA-256 as the hash function.
        The signature is not ASN.1 wrapped.

    - For COSEAlgorithmIdentifier -37 (PS256), `sig` MUST contain the signature generated using the
        RSASSA-PSS signature scheme defined in Section 8.1.1 of [[RFC8017]] with SHA-256 as the hash function.
        The signature is not ASN.1 wrapped.

# [=[WRP]=] Operations # {#sctn-rp-operations}

A [=registration ceremony|registration=] or [=authentication ceremony=] begins with the [=[WRP]=] creating a {{PublicKeyCredentialCreationOptions}}
or {{PublicKeyCredentialRequestOptions}} object, respectively, which encodes the parameters for the [=ceremony=]. The [=[RP]=]
SHOULD take care to not leak sensitive information during this stage; see [[#sctn-username-enumeration]] for details.

Upon successful execution of {{CredentialsContainer/create()}} or {{CredentialsContainer/get()}}, the [=[RP]=]'s script receives
a {{PublicKeyCredential}} containing an {{AuthenticatorAttestationResponse}} or {{AuthenticatorAssertionResponse}} structure,
respectively, from the client. It must then deliver the contents of this structure to the [=[RP]=] server, using methods outside
the scope of this specification. This section describes the operations that the [=[RP]=] must perform upon receipt of these
structures.


## Registering a New Credential ## {#sctn-registering-a-new-credential}

In order to perform a [=registration ceremony=], the [=[RP]=] MUST proceed as follows:

1. Let |options| be a new {{CredentialCreationOptions}} structure configured to the [=[RP]=]'s needs for the ceremony.
    Let |pkOptions| be <code>|options|.{{CredentialCreationOptions/publicKey}}</code>.

1. Call {{CredentialsContainer/create()|navigator.credentials.create()}} and pass |options| as the argument.
    Let |credential| be the result of the successfully resolved promise.
    If the promise is rejected, abort the ceremony with a user-visible error, or otherwise guide the user experience as
    might be determinable from the context available in the rejected promise. For example if the promise is rejected with
    an error code equivalent to "{{InvalidStateError}}", the user might be instructed to use a different [=authenticator=].
    For information on different error contexts and the circumstances leading to them, see [[#sctn-op-make-cred]].

1. Let |response| be <code>|credential|.{{PublicKeyCredential/response}}</code>.
    If |response| is not an instance of {{AuthenticatorAttestationResponse}}, abort the ceremony with a user-visible error.

1. Let |clientExtensionResults| be the result of calling
    <code>|credential|.{{PublicKeyCredential/getClientExtensionResults()}}</code>.

1. Let |JSONtext| be the result of
    running [=UTF-8 decode=] on the value of <code>|response|.{{AuthenticatorResponse/clientDataJSON}}</code>.

    Note: Using any implementation of [=UTF-8 decode=] is acceptable as long as it yields the same result as that yielded by
    the [=UTF-8 decode=] algorithm. In particular, any leading byte order mark (BOM) must be stripped.

1. Let |C|, the [=client data=] claimed as collected during the credential creation, be the result of running an
    implementation-specific JSON parser on |JSONtext|.

    Note: |C| may be any implementation-specific data structure representation, as long as |C|'s components are referenceable, as
    required by this algorithm.

1. Verify that the value of <code>|C|.{{CollectedClientData/type}}</code> is `webauthn.create`.

1. Verify that the value of <code>|C|.{{CollectedClientData/challenge}}</code> equals
    the base64url encoding of <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/challenge}}</code>.

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list :-/
-->
    <li id='rp-op-registering-a-new-credential-step-origin'>
      Verify that the value of <code>|C|.{{CollectedClientData/origin}}</code> is an [=origin=] expected by the [=[RP]=].
      See [[#sctn-validating-origin]] for guidance.
    </li>

1. If <code>|C|.{{CollectedClientData/crossOrigin}}</code> is present and set to [TRUE],
    verify that the [=[RP]=] expects that this credential would have been created within an iframe
    that is not [=same-origin with its ancestors=].

1. If <code>|C|.{{CollectedClientData/topOrigin}}</code> is present:

    1. Verify that the [=[RP]=] expects that this credential would have been created within an iframe that is
        not [=same-origin with its ancestors=].

    1. Verify that the value of <code>|C|.{{CollectedClientData/topOrigin}}</code> matches the [=origin=] of a page
        that the [=[RP]=] expects to be sub-framed within.
        See [[#sctn-validating-origin]] for guidance.

1. Let |hash| be the result of computing a hash over <code>|response|.{{AuthenticatorResponse/clientDataJSON}}</code> using SHA-256.

1. Perform CBOR decoding on the {{AuthenticatorAttestationResponse/attestationObject}} field of the
    {{AuthenticatorAttestationResponse}} structure to obtain the attestation statement format |fmt|, the [=authenticator data=]
    |authData|, and the attestation statement |attStmt|.

1. Verify that the <code>[=rpIdHash=]</code> in |authData| is the SHA-256 hash of the [=RP ID=] expected by the [=[RP]=].

1. If <code>|options|.{{CredentialCreationOptions/mediation}}</code> is not set to {{CredentialMediationRequirement/conditional}},
    verify that the [=UP=] bit of the <code>[=flags=]</code> in |authData| is set.

1. If the [=[RP]=] requires [=user verification=] for this registration,
    verify that the [=authData/flags/UV=] bit of the <code>[=flags=]</code> in |authData| is set.

1. If the [=authData/flags/BE=] bit of the <code>[=flags=]</code> in |authData| is not set, verify that the [=authData/flags/BS=] bit is not set.

1. If the [=[RP]=] uses the credential's [=backup eligibility=] to inform its user experience flows and/or policies, evaluate the
    [=authData/flags/BE=] bit of the <code>[=flags=]</code> in |authData|.

1. If the [=[RP]=] uses the credential's [=backup state=] to inform its user experience flows and/or policies, evaluate the [=authData/flags/BS=]
    bit of the <code>[=flags=]</code> in |authData|.

1. Verify that the "alg" parameter in the [=credentialPublicKey|credential public key=] in |authData|
    matches the {{PublicKeyCredentialParameters/alg}} attribute of one of the [=list/items=] in
    <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/pubKeyCredParams}}</code>.

1. Determine the attestation statement format by performing a USASCII case-sensitive match on |fmt| against the set of
    supported WebAuthn Attestation Statement Format Identifier values.
    An up-to-date list of registered WebAuthn Attestation Statement Format Identifier values
    is maintained in the
    IANA "WebAuthn Attestation Statement Format Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]].

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list -->
    <li id="reg-ceremony-verify-attestation">
        Verify that |attStmt| is a correct [=attestation statement=], conveying a valid [=attestation signature=], by using the
        [=attestation statement format=] |fmt|'s [=verification procedure=] given |attStmt|, |authData| and |hash|.

        Note: Each [=attestation statement format=] specifies its own [=verification procedure=]. See [[#sctn-defined-attestation-formats]] for
        the initially-defined formats, and [[!IANA-WebAuthn-Registries]] for the up-to-date list.
    </li>

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list -->
    <li id="reg-ceremony-attestation-trust-anchors">
        If validation is successful, obtain a list of acceptable trust anchors (i.e. attestation root certificates)
        for that attestation type and attestation statement format |fmt|, from a trusted source or from policy. For
        example, the FIDO Metadata Service [[FIDOMetadataService]] provides one way to obtain such information, using the
        <code>[=authData/attestedCredentialData/aaguid=]</code> in the <code>[=attestedCredentialData=]</code> in |authData|.
    </li>

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list -->
    <li id="reg-ceremony-assess-trust">
        Assess the attestation trustworthiness using the outputs of the [=verification procedure=] in [step 21](#reg-ceremony-verify-attestation), as follows:
            - If [=None|no attestation=] was provided, verify that [=None=] attestation is acceptable under [=[RP]=] policy.
            - If [=self attestation=] was used, verify that [=self attestation=] is acceptable under [=[RP]=] policy.
            - Otherwise, use the X.509 certificates returned as the [=attestation trust path=] from the [=verification procedure=]
                to verify that the attestation public key either correctly chains up to an acceptable root certificate, or is itself an acceptable certificate
                (i.e., it and the root certificate obtained in [step 22](#reg-ceremony-attestation-trust-anchors) may be the same).

        If the attestation statement is not deemed trustworthy, the [=[RP]=] SHOULD fail the [=registration ceremony=].

        NOTE: However, if permitted by policy, the [=[RP]=] MAY register the [=credential ID=] and credential public key but treat the
            credential as one with [=self attestation=] (see [[#sctn-attestation-types]]). If doing so, the [=[RP]=] is asserting there
            is no cryptographic proof that the [=public key credential=] has been generated by a particular [=authenticator=] model.
            See [[FIDOSecRef]] and [[UAFProtocol]] for a more detailed discussion.
    </li>

1. Verify that the <code>[=credentialId=]</code> is &le; 1023 bytes. Credential IDs larger than this many bytes SHOULD cause the RP to fail this [=registration ceremony=].

1. Verify that the <code>[=credentialId=]</code> is not yet registered for any user. If the <code>[=credentialId=]</code> is already known then the [=[RP]=] SHOULD fail this [=registration ceremony=].

    Note: The rationale for [=[RPS]=] rejecting duplicate [=credential IDs=] is as follows:
    [=credential IDs=] contain sufficient entropy that accidental duplication is very unlikely. However, [=attestation types=] other than [=self attestation=] do not include a self-signature to explicitly prove possession of the [=credential private key=] at [=registration=] time. Thus an attacker who has managed to obtain a user's [=credential ID=] and [=credential public key=] for a site (this could be potentially accomplished in various ways), could attempt to register a victim's credential as their own at that site. If the [=[RP]=] accepts this new registration and replaces the victim's existing credential registration, and the [=discoverable credentials|credentials are discoverable=], then the victim could be forced to sign into the attacker's account at their next attempt. Data saved to the site by the victim in that state would then be available to the attacker.

    <li id="reg-ceremony-create-credential-record">
        Let |credentialRecord| be a new [=credential record=] with the following contents:

        <dl>
            :   [$credential record/type$]
            ::  <code>|credential|.{{Credential/type}}</code>.

            :   [$credential record/id$]
            ::  <code>|credential|.{{Credential/id}}</code> or <code>|credential|.{{PublicKeyCredential/rawId}}</code>,
                whichever format is preferred by the [=[RP]=].

            :   [$credential record/publicKey$]
            ::  The [=credential public key=] in |authData|.

            :   [$credential record/signCount$]
            ::  <code>|authData|.[=authData/signCount=]</code>.

            :   [$credential record/uvInitialized$]
            ::  The value of the [=authData/flags/UV=] [=flag=] in |authData|.

            :   [$credential record/transports$]
            ::  The value returned from <code>|response|.{{AuthenticatorAttestationResponse/getTransports()}}</code>.

            :   [$credential record/backupEligible$]
            ::  The value of the [=authData/flags/BE=] [=flag=] in |authData|.

            :   [$credential record/backupState$]
            ::  The value of the [=authData/flags/BS=] [=flag=] in |authData|.
        </dl>

        The new [=credential record=] MAY also include the following OPTIONAL contents:

        <dl>
            :   [$credential record/attestationObject$]
            ::  <code>|response|.{{AuthenticatorAttestationResponse/attestationObject}}</code>.

            :   [$credential record/attestationClientDataJSON$]
            ::  <code>|response|.{{AuthenticatorResponse/clientDataJSON}}</code>.
        </dl>

        The [=[RP]=] MAY also include any additional [=struct/items=] as necessary.
        As a non-normative example, the [=[RP]=] might allow the user to set a "nickname" for the credential
        to help the user remember which [=credential=] is [=bound credential|bound=] to which [=authenticator=]
        when interacting with account settings.
    </li>

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list -->
    <li id='reg-ceremony-verify-extension-outputs'>
        Process the [=client extension outputs=] in |clientExtensionResults|
        and the [=authenticator extension outputs=] in the <code>[=authData/extensions=]</code> in |authData|
        as required by the [=[RP]=].
        Depending on each [=WebAuthn extensions|extension=],
        processing steps may be concretely specified or it may be up to the [=[RP]=] what to do with extension outputs.
        The [=[RP]=] MAY ignore any or all extension outputs.

        [=Clients=] MAY set additional [=authenticator extensions=] or
        [=client extensions=] and thus cause values to appear in the [=authenticator extension outputs=] or
        [=client extension outputs=] that were not
        requested by the [=[RP]=] in <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/extensions}}</code>.
        The [=[RP]=] MUST be prepared to handle such situations,
        whether by ignoring the unsolicited extensions or by rejecting the attestation. The [=[RP]=] can make this
        decision based on local policy and the extensions in use.

        Since all extensions are OPTIONAL for both the [=client=] and the [=authenticator=], the [=[RP]=] MUST also be
        prepared to handle cases where none or not all of the requested extensions were acted upon.
    </li>

1. If all the above steps are successful,
    store |credentialRecord| in the [=user account=] that was denoted in <code>|pkOptions|.{{PublicKeyCredentialCreationOptions/user}}</code>
    and continue the [=registration ceremony=] as appropriate.
    Otherwise, fail the [=registration ceremony=].

    If the [=[RP]=] does not fail the [=registration ceremony=] in this case,
    then the [=[RP]=] is accepting that there is no cryptographic proof
    that the [=public key credential=] has been generated by any particular [=authenticator=] model.
    The [=[RP]=] MAY consider the credential as equivalent to one with [=None|no attestation=] (see [[#sctn-attestation-types]]).
    See [[FIDOSecRef]] and [[UAFProtocol]] for a more detailed discussion.

    Verification of [=attestation objects=] requires that the [=[RP]=] has a trusted method of determining acceptable trust anchors
    in [step 22](#reg-ceremony-attestation-trust-anchors) above.
    Also, if certificates are being used, the [=[RP]=] MUST have access to certificate status information for the
    intermediate CA certificates. The [=[RP]=] MUST also be able to build the attestation certificate chain if the client did not
    provide this chain in the attestation information.

## Verifying an Authentication Assertion ## {#sctn-verifying-assertion}

In order to perform an [=authentication ceremony=], the [=[RP]=] MUST proceed as follows:

1. Let |options| be a new {{CredentialRequestOptions}} structure configured to the [=[RP]=]'s needs for the ceremony.
    Let |pkOptions| be <code>|options|.{{CredentialRequestOptions/publicKey}}</code>.

1. Call {{CredentialsContainer/get()|navigator.credentials.get()}} and pass |options| as the argument.
    Let |credential| be the result of the successfully resolved promise.
    If the promise is rejected, abort the ceremony with a user-visible error, or otherwise guide the user experience as might
    be determinable from the context available in the rejected promise. For information on different error contexts and the
    circumstances leading to them, see [[#sctn-op-get-assertion]].

1. Let |response| be <code>|credential|.{{PublicKeyCredential/response}}</code>.
    If |response| is not an instance of {{AuthenticatorAssertionResponse}}, abort the ceremony with a user-visible error.

1. Let |clientExtensionResults| be the result of calling <code>|credential|.{{PublicKeyCredential/getClientExtensionResults()}}</code>.

1. If <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code> [=list/is not empty=],
    verify that <code>|credential|.{{Credential/id}}</code> identifies one of the [=public key credentials=]
    listed in <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/allowCredentials}}</code>.

1. Identify the user being authenticated and let |credentialRecord|
    be the [=credential record=] for the [=credential=]:

    <dl class="switch">
        :  If the user was identified before the [=authentication ceremony=] was initiated, e.g., via a username or cookie,
        :: verify that the identified [=user account=] contains a [=credential record=]
            whose [$credential record/id$] equals <code>|credential|.{{PublicKeyCredential/rawId}}</code>.
            Let |credentialRecord| be that [=credential record=].
            If <code>|response|.{{AuthenticatorAssertionResponse/userHandle}}</code> is present,
            verify that it equals the [=user handle=] of the [=user account=].

        :  If the user was not identified before the [=authentication ceremony=] was initiated,
        :: verify that <code>|response|.{{AuthenticatorAssertionResponse/userHandle}}</code> is present.
            Verify that the [=user account=] identified by <code>|response|.{{AuthenticatorAssertionResponse/userHandle}}</code>
            contains a [=credential record=] whose [$credential record/id$] equals <code>|credential|.{{PublicKeyCredential/rawId}}</code>.
            Let |credentialRecord| be that [=credential record=].
    </dl>

1. Let |cData|, |authData| and |sig| denote the value of |response|'s
    {{AuthenticatorResponse/clientDataJSON}}, {{AuthenticatorAssertionResponse/authenticatorData}}, and
    {{AuthenticatorAssertionResponse/signature}} respectively.

1. Let |JSONtext| be the result of running [=UTF-8 decode=] on the value of |cData|.

    Note: Using any implementation of [=UTF-8 decode=] is acceptable as long as it yields the same result as that yielded by
    the [=UTF-8 decode=] algorithm. In particular, any leading byte order mark (BOM) must be stripped.

1. Let |C|, the [=client data=] claimed as used for the signature, be the result of running an implementation-specific
    JSON parser on |JSONtext|.

    Note: |C| may be any implementation-specific data structure representation, as long as |C|'s components are referenceable, as
    required by this algorithm.

1. Verify that the value of <code>|C|.{{CollectedClientData/type}}</code> is the string `webauthn.get`.

1. Verify that the value of <code>|C|.{{CollectedClientData/challenge}}</code> equals
    the base64url encoding of <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/challenge}}</code>.

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list :-/
-->
    <li id='rp-op-verifying-assertion-step-origin'>
      Verify that the value of <code>|C|.{{CollectedClientData/origin}}</code> is an [=origin=] expected by the [=[RP]=].
      See [[#sctn-validating-origin]] for guidance.
    </li>

1. If <code>|C|.{{CollectedClientData/crossOrigin}}</code> is present and set to [TRUE],
    verify that the [=[RP]=] expects this credential to be used within an iframe that is not [=same-origin with its ancestors=].

1. If <code>|C|.{{CollectedClientData/topOrigin}}</code> is present:

    1. Verify that the [=[RP]=] expects this credential to be used within an iframe that is not [=same-origin with its ancestors=].

    1. Verify that the value of <code>|C|.{{CollectedClientData/topOrigin}}</code> matches the [=origin=] of a page
        that the [=[RP]=] expects to be sub-framed within.
        See [[#sctn-validating-origin]] for guidance.

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as
a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list :-/
-->
    <li id='rp-op-verifying-assertion-step-rpid-hash'>
      Verify that the <code>[=rpIdHash=]</code> in |authData| is the SHA-256 hash of the [=RP ID=] expected by the [=[RP]=].

      Note: If using the [=appid=] extension, this step needs some special logic. See [[#sctn-appid-extension]] for details.
    </li>

1. Verify that the [=UP=] bit of the <code>[=flags=]</code> in |authData| is set.

1. Determine whether [=user verification=] is required for this assertion.
    [=User verification=] SHOULD be required if, and only if,
    <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/userVerification}}</code> is set to {{UserVerificationRequirement/required}}.

    If [=user verification=] was determined to be required,
    verify that the [=authData/flags/UV=] bit of the <code>[=flags=]</code> in |authData| is set.
    Otherwise, ignore the value of the [=authData/flags/UV=] [=flag=].

1. If the [=authData/flags/BE=] bit of the <code>[=flags=]</code> in |authData| is not set, verify that the [=authData/flags/BS=] bit is not set.

1. If the credential [=backup state=] is used as part of [=[RP]=] business logic or policy,
    let |currentBe| and |currentBs| be the values of the [=authData/flags/BE=] and [=authData/flags/BS=] bits, respectively,
    of the <code>[=flags=]</code> in |authData|.
    Compare |currentBe| and |currentBs| with
    <code>|credentialRecord|.[$credential record/backupEligible$]</code> and <code>|credentialRecord|.[$credential record/backupState$]</code>:

    1. If <code>|credentialRecord|.[$credential record/backupEligible$]</code> is set, verify that |currentBe| is set.

    1. If <code>|credentialRecord|.[$credential record/backupEligible$]</code> is not set, verify that |currentBe| is not set.

    1. Apply [=[RP]=] policy, if any.

    Note: See [[#sctn-credential-backup]] for examples of how a [=[RP]=] might process the [=authData/flags/BS=] [=flag=] values.

1. Let |hash| be the result of computing a hash over the |cData| using SHA-256.

1. Using <code>|credentialRecord|.[$credential record/publicKey$]</code>,
    verify that |sig| is a valid signature over the binary concatenation of
    |authData| and |hash|.

    Note: This verification step is compatible with signatures generated by FIDO U2F authenticators. See
    [[#sctn-fido-u2f-sig-format-compat]].

1. If |authData|.<code>[=authData/signCount=]</code> is nonzero or <code>|credentialRecord|.[$credential record/signCount$]</code> is nonzero,
    then run the following sub-step:
      - If |authData|.<code>[=authData/signCount=]</code> is
           <dl class="switch">
              <dt>greater than <code>|credentialRecord|.[$credential record/signCount$]</code>:</dt>
              <dd>The signature counter is valid.</dd>
              <dt>less than or equal to <code>|credentialRecord|.[$credential record/signCount$]</code>:</dt>
              <dd>This is a signal, but not proof, that the authenticator may be cloned. For example it might mean that:
                  - Two or more copies of the [=credential private key=] may exist and are being used in parallel. 
                  - An authenticator is malfunctioning.
                  - A race condition exists where the [=[RP]=] is processing assertion responses in an order other than the order they were generated at the authenticator.
                  
                  [=[RPS]=] should evaluate their own operational characteristics and incorporate this information into their risk scoring.
                  Whether the [=[RP]=] updates <code>|credentialRecord|.[$credential record/signCount$]</code>
                  below in this case, or not, or fails the [=authentication ceremony=] or not, is [=[RP]=]-specific. 

                  For more information on signature counter considerations, see [[#sctn-sign-counter]].
              </dd>
           </dl>

<!-- Note: this next step is actually a top-level step, but bikeshed wanted it indented this much in order to render it as a numbered step. If outdented, it (today) is rendered as a bullet in the midst of a numbered list -->
    <li id='authn-ceremony-verify-extension-outputs'>
        Process the [=client extension outputs=] in |clientExtensionResults|
        and the [=authenticator extension outputs=] in the <code>[=authData/extensions=]</code> in |authData|
        as required by the [=[RP]=].
        Depending on each [=WebAuthn extensions|extension=],
        processing steps may be concretely specified or it may be up to the [=[RP]=] what to do with extension outputs.
        The [=[RP]=] MAY ignore any or all extension outputs.

        [=Clients=] MAY set additional [=authenticator extensions=] or
        [=client extensions=] and thus cause values to appear in the [=authenticator extension outputs=] or
        [=client extension outputs=] that were not
        requested by the [=[RP]=] in <code>|pkOptions|.{{PublicKeyCredentialRequestOptions/extensions}}</code>.
        The [=[RP]=] MUST be prepared to handle such situations,
        whether by ignoring the unsolicited extensions or by rejecting the assertion. The [=[RP]=] can make this
        decision based on local policy and the extensions in use.

        Since all extensions are OPTIONAL for both the [=client=] and the [=authenticator=], the [=[RP]=] MUST also be
        prepared to handle cases where none or not all of the requested extensions were acted upon.
    </li>

    <li id='authn-ceremony-update-credential-record'>
        Update |credentialRecord| with new state values:

            1. Update <code>|credentialRecord|.[$credential record/signCount$]</code> to the value of |authData|.<code>[=authData/signCount=]</code>.
            1. Update <code>|credentialRecord|.[$credential record/backupState$]</code> to the value of |currentBs|.
            1. If <code>|credentialRecord|.[$credential record/uvInitialized$]</code> is [FALSE],
                update it to the value of the [=authData/flags/UV=] bit in the [=flags=] in |authData|.
                This change SHOULD require authorization by an additional [=authentication factor=] equivalent to WebAuthn [=user verification=];
                if not authorized, skip this step.

        If the [=[RP]=] performs additional security checks beyond these WebAuthn [=authentication ceremony=] steps,
        the above state updates SHOULD be deferred to after those additional checks are completed successfully.
    </li>

1. If all the above steps are successful, continue the [=authentication ceremony=] as appropriate. Otherwise, fail the
    [=authentication ceremony=].


# Defined Attestation Statement Formats # {#sctn-defined-attestation-formats}

WebAuthn supports pluggable attestation statement formats. This section defines an initial set of such formats.

## Attestation Statement Format Identifiers ## {#sctn-attstn-fmt-ids}

Attestation statement formats are identified by a string, called an <dfn>attestation statement format identifier</dfn>, chosen by
the author of the [=attestation statement format=].

Attestation statement format identifiers SHOULD be registered in the
IANA "WebAuthn Attestation Statement Format Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]].
All registered attestation statement format identifiers are unique amongst themselves as a matter of course.

Unregistered attestation statement format identifiers SHOULD use lowercase reverse domain-name naming, using a domain name
registered by the developer, in order to assure uniqueness of the identifier. All attestation statement format identifiers MUST
be a maximum of 32 octets in length and MUST consist only of printable USASCII characters, excluding backslash and doublequote,
i.e., VCHAR as defined in [[!RFC5234]] but without %x22 and %x5c.

Note: This means attestation statement format identifiers based on domain names are restricted to incorporating only LDH Labels [[!RFC5890]].

Implementations MUST match WebAuthn attestation statement format identifiers in a case-sensitive fashion.

Attestation statement formats that may exist in multiple versions SHOULD include a version in their identifier. In effect,
different versions are thus treated as different formats, e.g., `packed2` as a new version of the [[#sctn-packed-attestation]].

The following sections present a set of currently-defined and registered attestation statement formats and their identifiers.
The up-to-date list of registered [=attestation statement format identifiers=] is maintained in the
IANA "WebAuthn Attestation Statement Format Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]].


## Packed Attestation Statement Format ## {#sctn-packed-attestation}

This is a WebAuthn optimized attestation statement format. It uses a very compact but still extensible encoding method. It is
implementable by [=authenticators=] with limited resources (e.g., secure elements).

: Attestation statement format identifier
:: packed

: Attestation types supported
:: [=Basic=], [=Self=], [=AttCA=]

: Syntax
:: The syntax of a Packed Attestation statement is defined by the following CDDL:

    ```
    $$attStmtType //= (
                          fmt: "packed",
                          attStmt: packedStmtFormat
                      )

    packedStmtFormat = {
                           alg: COSEAlgorithmIdentifier,
                           sig: bytes,
                           x5c: [ attestnCert: bytes, * (caCert: bytes) ]
                       } //
                       {
                           alg: COSEAlgorithmIdentifier
                           sig: bytes,
                       }
    ```

    The semantics of the fields are as follows:

    : alg
    :: A {{COSEAlgorithmIdentifier}} containing the identifier of the algorithm used to generate the [=attestation signature=].

    : sig
    :: A byte string containing the [=attestation signature=].

    : x5c
    :: The elements of this array contain |attestnCert| and its certificate chain (if any), each encoded in X.509 format. The attestation
        certificate |attestnCert| MUST be the first element in the array.

    : attestnCert
    :: The attestation certificate, encoded in X.509 format.

: Signing procedure
:: The signing procedure for this attestation statement format is
    similar to [the procedure for generating assertion signatures](#fig-signature).
        1. Let |authenticatorData| denote the [=authenticator data for the attestation=],
            and let |clientDataHash| denote the [=hash of the serialized client data=].

        1. If [=Basic=] or [=AttCA=] [=attestation=] is in use, the authenticator produces the |sig| by concatenating |authenticatorData| and
            |clientDataHash|, and signing the result using an [=attestation private key=] selected through an authenticator-specific
            mechanism. It sets |x5c| to |attestnCert| followed by the related certificate chain (if any). It sets |alg| to the algorithm of the
            attestation private key.

        1. If [=self attestation=] is in use, the authenticator produces |sig| by concatenating |authenticatorData| and |clientDataHash|,
            and signing the result using the credential private key. It sets |alg| to the algorithm of the credential private key and
            omits the other fields.

: Verification procedure
:: Given the [=verification procedure inputs=] |attStmt|, |authenticatorData| and |clientDataHash|, the [=verification procedure=] is
    as follows:

        1. Verify that |attStmt| is valid CBOR conforming to the syntax defined above and perform CBOR decoding on it to extract
            the contained fields.

        1. If |x5c| is present:
            - Verify that |sig| is a valid signature over the concatenation of |authenticatorData| and |clientDataHash| using the
                attestation public key in |attestnCert| with the algorithm specified in |alg|.
            - Verify that |attestnCert| meets the requirements in [[#sctn-packed-attestation-cert-requirements]].
            - If |attestnCert| contains an extension with OID `1.3.6.1.4.1.45724.1.1.4` (`id-fido-gen-ce-aaguid`) verify that the
                value of this extension matches the <code>[=authData/attestedCredentialData/aaguid=]</code> in |authenticatorData|.
            - Optionally, inspect |x5c| and consult externally provided knowledge to determine whether |attStmt| conveys a
                [=Basic=] or [=AttCA=] attestation.
            - If successful, return implementation-specific values representing [=attestation type=] [=Basic=], [=AttCA=] or
                uncertainty, and [=attestation trust path=] |x5c|.

        1. If |x5c| is not present, [=self attestation=] is in use.
            - Validate that |alg| matches the algorithm of the <code>[=credentialPublicKey=]</code> in |authenticatorData|.
            - Verify that |sig| is a valid signature over the concatenation of |authenticatorData| and |clientDataHash| using the
                credential public key with |alg|.
            - If successful, return implementation-specific values representing [=attestation type=] [=Self=] and an empty
                [=attestation trust path=].


### Certificate Requirements for Packed Attestation Statements ### {#sctn-packed-attestation-cert-requirements}

The attestation certificate MUST have the following fields/extensions:

- Version MUST be set to 3 (which is indicated by an ASN.1 INTEGER with value 2).
- Subject field MUST be set to:
    : Subject-C
    :: ISO 3166 code specifying the country where the Authenticator vendor is incorporated (PrintableString)
    : Subject-O
    :: Legal name of the Authenticator vendor (UTF8String)
    : Subject-OU
    :: Literal string “Authenticator Attestation” (UTF8String)
    : Subject-CN
    :: A UTF8String of the vendor's choosing

- If the related attestation root certificate is used for multiple authenticator models, the Extension OID
    `1.3.6.1.4.1.45724.1.1.4` (`id-fido-gen-ce-aaguid`) MUST be present, containing the AAGUID as a 16-byte OCTET STRING.
    The extension MUST NOT be marked as critical.

    As [=[RPS]=] may not know if the attestation root
    certificate is used for multiple authenticator models, it is suggested that [=[RPS]=] check if the extension
    is present, and if it is, then validate that it contains that same AAGUID as presented in the [=attestation object=].

    Note that an X.509 Extension encodes the DER-encoding of the value in an OCTET STRING.
    Thus, the AAGUID MUST be wrapped in <i>two</i> OCTET STRINGS to be valid.

- The Basic Constraints extension MUST have the CA component set to [FALSE].

Additionally, an Authority Information Access (AIA) extension with entry `id-ad-ocsp` and a CRL Distribution Point extension
    [[RFC5280]] are both OPTIONAL as the status of many attestation certificates is available through authenticator metadata
    services. See, for example, the FIDO Metadata Service [[FIDOMetadataService]].

The firmware of a particular authenticator model MAY be differentiated using the Extension OID `1.3.6.1.4.1.45724.1.1.5`
    (`id-fido-gen-ce-fw-version`). When present, this attribute contains an INTEGER with a non-negative value which is incremented for new
    firmware release versions. The extension MUST NOT be marked as critical.

For example, the following is an attestation certificate containing the above extension OIDs as well as required fields:

~~~ pem
-----BEGIN CERTIFICATE-----
MIIBzTCCAXOgAwIBAgIUYHS3FJEL/JTfFqafuAHvlAS+hDYwCgYIKoZIzj0EAwIw
QTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC1dlYkF1dGhuIFdHMRwwGgYDVQQDDBNF
eGFtcGxlIEF0dGVzdGF0aW9uMCAXDTI0MDEwMzE3NDUyMVoYDzIwNTAwMTA2MTc0
NTIxWjBBMQswCQYDVQQGEwJVUzEUMBIGA1UECgwLV2ViQXV0aG4gV0cxHDAaBgNV
BAMME0V4YW1wbGUgQXR0ZXN0YXRpb24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
AATDQN9uaFFH4BKBjthHTM1drpb7gIuPod67qyF6UdL4qah6XUp6tE7Prl+DfQ7P
YH9yMOOcci3nr+Q/jOBaWVERo0cwRTAhBgsrBgEEAYLlHAEBBAQSBBDNjDlcJu3u
3mU7AHl9A8o8MBIGCysGAQQBguUcAQEFBAMCASowDAYDVR0TAQH/BAIwADAKBggq
hkjOPQQDAgNIADBFAiA3k3aAUVtLhDHLXOgY2kRnK2hrbRgf2EKdTDLJ1Ds/RAIh
AOmIblhI3ALCHOaO0IO7YlMpw/lSTvFYv3qwO3m7H8Dc
-----END CERTIFICATE-----
~~~

The attributes above are structured within this certificate as such:

~~~ text
30 21                                    -- SEQUENCE
  06 0B 2B 06 01 04 01 82 E5 1C 01 01 04 -- OID 1.3.6.1.4.1.45724.1.1.4
  04 12                                  -- OCTET STRING
    04  10                               -- OCTET STRING
      CD 8C 39 5C 26 ED EE DE            -- AAGUID cd8c395c-26ed-eede-653b-00797d03ca3c
      65 3B 00 79 7D 03 CA 3C 

30 12                                    -- SEQUENCE
  06 0B 2B 06 01 04 01 82 E5 1C 01 01 05 -- OID 1.3.6.1.4.1.45724.1.1.5
  04 03                                  -- OCTET STRING
    02 01                                -- INTEGER
      2A                                 -- Firmware version: 42
~~~

### Certificate Requirements for Enterprise Packed Attestation Statements ### {#sctn-enterprise-packed-attestation-cert-requirements}

The Extension OID `1.3.6.1.4.1.45724.1.1.2` ( `id-fido-gen-ce-sernum` ) MAY additionally be present in packed attestations for enterprise use. If present, this extension MUST indicate a unique octet string value per device against a particular AAGUID. This value MUST remain constant through factory resets, but MAY be distinct from any other serial number or other hardware identifier associated with the device. This extension MUST NOT be marked as critical, and the corresponding value is encoded as an OCTET STRING. This extension MUST NOT be present in non-enterprise attestations.

## TPM Attestation Statement Format ## {#sctn-tpm-attestation}

This attestation statement format is generally used by authenticators that use a Trusted Platform Module as their cryptographic
engine.

: Attestation statement format identifier
:: tpm

: Attestation types supported
:: [=AttCA=]

: Syntax
:: The syntax of a TPM Attestation statement is as follows:

    ```
    $$attStmtType // = (
                           fmt: "tpm",
                           attStmt: tpmStmtFormat
                       )

    tpmStmtFormat = {
                        ver: "2.0",
                        (
                            alg: COSEAlgorithmIdentifier,
                            x5c: [ aikCert: bytes, * (caCert: bytes) ]
                        )
                        sig: bytes,
                        certInfo: bytes,
                        pubArea: bytes
                    }
    ```

    The semantics of the above fields are as follows:

    : ver
    :: The version of the TPM specification to which the signature conforms.

    : alg
    :: A {{COSEAlgorithmIdentifier}} containing the identifier of the algorithm used to generate the [=attestation signature=].

    : x5c
    :: |aikCert| followed by its certificate chain, in X.509 encoding.

    : aikCert
    :: The AIK certificate used for the attestation, in X.509 encoding.

    : sig
    :: The [=attestation signature=], in the form of a TPMT_SIGNATURE structure as specified in [[!TPMv2-Part2]] section 11.3.4.

    : certInfo
    :: The TPMS_ATTEST structure over which the above signature was computed, as specified in [[!TPMv2-Part2]] section 10.12.8.

    : pubArea
    :: The TPMT_PUBLIC structure (see [[!TPMv2-Part2]] section 12.2.4) used by the TPM to represent the credential public key.

: Signing procedure
:: Let |authenticatorData| denote the [=authenticator data for the attestation=], and let |clientDataHash| denote the
    [=hash of the serialized client data=].

    Concatenate |authenticatorData| and |clientDataHash| to form |attToBeSigned|.

    Generate a signature using the procedure specified in [[!TPMv2-Part3]] Section 18.2, using the attestation private key and
    setting the `extraData` parameter to the digest of |attToBeSigned| using the hash algorithm corresponding to the "alg" signature algorithm.
    (For the "RS256" algorithm, this would be a SHA-256 digest.)

    Set the |pubArea| field to the public area of the credential public key (the TPMT_PUBLIC structure), the |certInfo| field (the TPMS_ATTEST structure)
    to the output parameter of the same name, and the |sig| field to the signature obtained from the above procedure.

    Note: If the |pubArea| is read from the TPM using the TPM2_ReadPublic command, that command returns a TPM2B_PUBLIC structure. TPM2B_PUBLIC
    is two bytes of length followed by the TPMT_PUBLIC structure. The two bytes of length must be removed prior to putting this into the |pubArea|.

: Verification procedure
:: Given the [=verification procedure inputs=] |attStmt|, |authenticatorData| and |clientDataHash|, the [=verification procedure=] is
    as follows:

    Verify that |attStmt| is valid CBOR conforming to the syntax defined above and perform CBOR decoding on it to extract the
    contained fields.

    Verify that the public key specified by the `parameters` and `unique` fields of |pubArea| is identical to the
    <code>[=credentialPublicKey=]</code> in the <code>[=attestedCredentialData=]</code> in |authenticatorData|.

    Concatenate |authenticatorData| and |clientDataHash| to form |attToBeSigned|.

    Verify integrity of |certInfo|
    - Verify that |x5c| is present.
    - Verify that |aikCert| meets the requirements in [[#sctn-tpm-cert-requirements]].
    - If |aikCert| contains an extension with OID `1.3.6.1.4.1.45724.1.1.4` (`id-fido-gen-ce-aaguid`) verify that the value of this
        extension matches the <code>[=authData/attestedCredentialData/aaguid=]</code> in |authenticatorData|.
    - Verify the |sig| is a valid signature over |certInfo| using the attestation public key in |aikCert| with the
        algorithm specified in |alg|.

    Validate that |certInfo| is valid:
    Note: |certInfo| is a TPMS_ATTEST structure.
    - Verify that `magic` is set to `TPM_GENERATED_VALUE`.
    - Verify that `type` is set to `TPM_ST_ATTEST_CERTIFY`.
    - Verify that `extraData` is set to the hash of |attToBeSigned| using the hash algorithm employed in "alg".
    - Verify that `attested` contains a `TPMS_CERTIFY_INFO` structure as specified in [[!TPMv2-Part2]] section 10.12.3,
        whose `name` field contains a valid Name for |pubArea|, as computed using the procedure specified in [[!TPMv2-Part1]] section 16 using the nameAlg in the |pubArea|.

        Note: The TPM will always return TPMS_CERTIFY_INFO structure with the same nameAlg in the `name` as the nameAlg
        in |pubArea|.

        Note: The remaining fields in the "Standard Attestation Structure" [[!TPMv2-Part1]]
        section 31.2, i.e., `qualifiedSigner`, `clockInfo` and `firmwareVersion` are ignored.
        Depending on the properties of the |aikCert| key used, these fields may be obfuscated.
        If valid, these MAY be used as an input to risk engines.

    - If successful, return implementation-specific values representing [=attestation type=] [=AttCA=] and [=attestation trust
        path=] |x5c|.

### TPM Attestation Statement Certificate Requirements ### {#sctn-tpm-cert-requirements}

TPM [=attestation certificate=] MUST have the following fields/extensions:

- Version MUST be set to 3.

- Subject field MUST be set to empty.

- The Subject Alternative Name extension MUST be set as defined in [[!TPMv2-EK-Profile]] section 3.2.9.

        Note: Previous versions of [[!TPMv2-EK-Profile]] allowed the inclusion of an optional attribute,
        called HardwareModuleName, that contains the TPM serial number in the EK certificate.
        HardwareModuleName SHOULD NOT be placed in in the [=attestation certificate=]
        Subject Alternative Name.

- The Extended Key Usage extension MUST contain the OID `2.23.133.8.3`
    ("joint-iso-itu-t(2) internationalorganizations(23) 133 tcg-kp(8) tcg-kp-AIKCertificate(3)").

- The Basic Constraints extension MUST have the CA component set to [FALSE].

- An Authority Information Access (AIA) extension with entry `id-ad-ocsp` and a CRL Distribution Point extension [[RFC5280]] are
    both OPTIONAL as the status of many attestation certificates is available through metadata services.
    See, for example, the FIDO Metadata Service [[FIDOMetadataService]].


## Android Key Attestation Statement Format ## {#sctn-android-key-attestation}

When the [=authenticator=] in question is a [=platform authenticator=] on the Android "N" or later platform, the
attestation statement is based on the [Android key
attestation](https://source.android.com/security/keystore/attestation). In these cases, the attestation statement
is produced by a component running in a secure operating environment, but the [=authenticator data for the attestation=] is
produced outside this environment. The [=[WRP]=] is expected to check that the [=authenticator data claimed to have been used for
the attestation=] is consistent with the fields of the attestation certificate's extension data.


: Attestation statement format identifier
:: android-key

: Attestation types supported
:: [=Basic=]

: Syntax
:: An Android key attestation statement consists simply of the Android attestation statement, which is a series of
    DER encoded X.509 certificates. See
    [the Android developer documentation](https://developer.android.com/training/articles/security-key-attestation.html). Its
    syntax is defined as follows:

    ```
    $$attStmtType //= (
                          fmt: "android-key",
                          attStmt: androidStmtFormat
                      )

    androidStmtFormat = {
                          alg: COSEAlgorithmIdentifier,
                          sig: bytes,
                          x5c: [ credCert: bytes, * (caCert: bytes) ]
                        }

    ```

: Signing procedure
:: Let |authenticatorData| denote the [=authenticator data for the attestation=], and let |clientDataHash| denote the
    [=hash of the serialized client data=].

    Request an Android Key Attestation by calling <code>keyStore.getCertificateChain(myKeyUUID)</code> providing |clientDataHash| as the
    challenge value (e.g., by using <a
    href="https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder.html#setAttestationChallenge(byte%5B%5D)">
    setAttestationChallenge</a>). Set |x5c| to the returned value.

    The authenticator produces |sig| by concatenating |authenticatorData| and |clientDataHash|,
    and signing the result using the credential private key. It sets |alg| to the algorithm of the signature format.


: Verification procedure
:: Given the [=verification procedure inputs=] |attStmt|, |authenticatorData| and |clientDataHash|, the [=verification procedure=] is
    as follows:
    - Verify that |attStmt| is valid CBOR conforming to the syntax defined above and perform CBOR decoding on it to extract the
        contained fields.
    - Verify that |sig| is a valid signature over the concatenation of |authenticatorData| and |clientDataHash| using the
        public key in the first certificate in |x5c| with the algorithm specified in |alg|.
    - Verify that the public key in the first certificate in |x5c| matches the
        <code>[=credentialPublicKey=]</code> in the <code>[=attestedCredentialData=]</code> in |authenticatorData|.
    - Verify that the `attestationChallenge` field in the [=attestation certificate=]
        [=android key attestation certificate extension data|extension data=] is identical to |clientDataHash|.
    - Verify the following using the appropriate authorization list from the attestation certificate
        [=android key attestation certificate extension data|extension data=]:
        - The `AuthorizationList.allApplications` field is <em>not</em> present on either authorization list
            (`softwareEnforced` nor `teeEnforced`), since PublicKeyCredential MUST be [=scoped=] to the [=RP ID=].
        - For the following, use only the `teeEnforced` authorization list if the RP wants to accept only keys from a
            trusted execution environment, otherwise use the union of `teeEnforced` and `softwareEnforced`.
            - The value in the `AuthorizationList.origin` field is equal to `KM_ORIGIN_GENERATED`.
            - The value in the `AuthorizationList.purpose` field is equal to `KM_PURPOSE_SIGN`.
    - If successful, return implementation-specific values representing [=attestation type=] [=Basic=] and [=attestation trust
        path=] |x5c|.

### Android Key Attestation Statement Certificate Requirements ### {#sctn-key-attstn-cert-requirements}

Android Key Attestation [=attestation certificate=]'s <dfn>android key attestation certificate extension
data</dfn> is identified by the OID `1.3.6.1.4.1.11129.2.1.17`, and its schema is defined in the [Android developer documentation](https://developer.android.com/training/articles/security-key-attestation#certificate_schema).

## Android SafetyNet Attestation Statement Format ## {#sctn-android-safetynet-attestation}

Note: This format is deprecated and is expected to be removed in a future revision of this document.

When the [=authenticator=] is a [=platform authenticator=] on certain Android platforms, the attestation
statement may be based on the [SafetyNet API](https://developer.android.com/training/safetynet/attestation#compat-check-response). In
this case the [=authenticator data=] is completely controlled by the caller of the SafetyNet API (typically an application
running on the Android platform) and the attestation statement  provides some statements about the health of the platform
and the identity of the calling application
(see [SafetyNet Documentation](https://developer.android.com/training/safetynet/attestation.html) for more details).

: Attestation statement format identifier
:: android-safetynet

: Attestation types supported
:: [=Basic=]

: Syntax
:: The syntax of an Android Attestation statement is defined as follows:

    ```
    $$attStmtType //= (
                          fmt: "android-safetynet",
                          attStmt: safetynetStmtFormat
                      )

    safetynetStmtFormat = {
                              ver: text,
                              response: bytes
                          }
    ```

    The semantics of the above fields are as follows:

    : ver
    :: The version number of Google Play Services responsible for providing the SafetyNet API.

    : response
    :: The [=UTF-8 encoded=] result of the getJwsResult() call of the SafetyNet API. This value is a JWS [[!RFC7515]] object (see
        [SafetyNet online documentation](https://developer.android.com/training/safetynet/attestation#compat-check-response))
        in Compact Serialization.

: Signing procedure
:: Let |authenticatorData| denote the [=authenticator data for the attestation=], and let |clientDataHash| denote the
    [=hash of the serialized client data=].

    Concatenate |authenticatorData| and |clientDataHash|, perform SHA-256 hash of the concatenated string, and
    let the result of the hash form |attToBeSigned|.

    Request a SafetyNet attestation, providing |attToBeSigned| as the nonce value. Set |response| to the result, and |ver| to
    the version of Google Play Services running in the authenticator.

: Verification procedure
:: Given the [=verification procedure inputs=] |attStmt|, |authenticatorData| and |clientDataHash|, the [=verification procedure=] is
    as follows:
    - Verify that |attStmt| is valid CBOR conforming to the syntax defined above and perform CBOR decoding on it to extract the
        contained fields.
    - Verify that |response| is a valid SafetyNet response of version |ver|
        by following the steps indicated by the [SafetyNet online documentation](https://developer.android.com/training/safetynet/attestation.html#compat-check-response).
        As of this writing, there is only one format of the SafetyNet response and |ver| is reserved for future use.
    - Verify that the `nonce` attribute in the payload of |response| is identical to the Base64 encoding of the SHA-256 hash of the concatenation of |authenticatorData| and |clientDataHash|.
    - Verify that the SafetyNet response actually came from the SafetyNet service by following the steps in the
        [SafetyNet online documentation](https://developer.android.com/training/safetynet/attestation#compat-check-response).
    - If successful, return implementation-specific values representing [=attestation type=] [=Basic=] and [=attestation trust
        path=] |x5c|.


## FIDO U2F Attestation Statement Format ## {#sctn-fido-u2f-attestation}

This attestation statement format is used with FIDO U2F authenticators using the formats defined in
[[FIDO-U2F-Message-Formats]].

: Attestation statement format identifier
:: fido-u2f

: Attestation types supported
:: [=Basic=], [=AttCA=]

: Syntax
:: The syntax of a FIDO U2F attestation statement is defined as follows:

    ```
    $$attStmtType //= (
                          fmt: "fido-u2f",
                          attStmt: u2fStmtFormat
                      )

    u2fStmtFormat = {
                        x5c: [ attestnCert: bytes ],
                        sig: bytes
                    }
    ```

    The semantics of the above fields are as follows:

    : x5c
    :: A single element array containing the attestation certificate in X.509 format.

    : sig
    :: The [=attestation signature=].
        The signature was calculated over the (raw) U2F registration response message [[!FIDO-U2F-Message-Formats]]
        received by the [=client=] from the authenticator.

: Signing procedure
:: If the [=credential public key=] of the [=attestedCredentialData|attested credential=] is not of algorithm -7 ("ES256"), stop and return an error.
    Otherwise, let |authenticatorData| denote the [=authenticator data for the attestation=],
    and let |clientDataHash| denote the [=hash of the serialized client data=]. (Since SHA-256 is used to hash the
    serialized [=client data=], |clientDataHash| will be 32 bytes long.)

    Generate a Registration Response Message as specified in [[!FIDO-U2F-Message-Formats]] [=Section 4.3=], with the application parameter set to the
    SHA-256 hash of the [=RP ID=] that the given [=public key credential|credential=] is [=scoped=] to, the challenge parameter set to |clientDataHash|, and the key handle
    parameter set to the [=credential ID=] of the given credential. Set the raw signature part of this Registration Response Message (i.e., without the [=user public key=],
    key handle, and attestation certificates) as |sig| and set the attestation certificates of
    the attestation public key as |x5c|.

: Verification procedure
:: Given the [=verification procedure inputs=] |attStmt|, |authenticatorData| and |clientDataHash|, the [=verification procedure=] is
    as follows:
    1. Verify that |attStmt| is valid CBOR conforming to the syntax defined above and perform CBOR decoding on it to extract the
        contained fields.
    1. Check that |x5c| has exactly one element and let |attCert| be that element. Let |certificate public key| be the public key
        conveyed by |attCert|. If |certificate public key| is not an Elliptic Curve (EC) public
        key over the P-256 curve, terminate this algorithm and return an appropriate error.
    1. Extract the claimed |rpIdHash| from |authenticatorData|, and the claimed |credentialId| and |credentialPublicKey| from
        |authenticatorData|.<code>[=attestedCredentialData=]</code>.
    1. Convert the COSE_KEY formatted |credentialPublicKey| (see [=Section 7=] of [[!RFC9052]]) to Raw ANSI X9.62 public key
        format (see ALG_KEY_ECC_X962_RAW in [=Section 3.6.2 Public Key Representation Formats=] of [[!FIDO-Registry]]).
        - Let |x| be the value corresponding to the "-2" key (representing x coordinate) in |credentialPublicKey|, and confirm its
            size to be of 32 bytes.
            If size differs or "-2" key is not found, terminate this algorithm and return an appropriate error.
        - Let |y| be the value corresponding to the "-3" key (representing y coordinate) in |credentialPublicKey|, and confirm its
            size to be of 32 bytes.
            If size differs or "-3" key is not found, terminate this algorithm and return an appropriate error.
        - Let |publicKeyU2F| be the concatenation <code>0x04 || |x| || |y|</code>.

            Note: This signifies uncompressed ECC key format.
    1. Let |verificationData| be the concatenation of (0x00 || |rpIdHash| ||
        |clientDataHash| || |credentialId| || |publicKeyU2F|) (see [=Section 4.3=] of [[!FIDO-U2F-Message-Formats]]).
    1. Verify the |sig| using |verificationData| and the |certificate public key| per section 4.1.4 of [[!SEC1]] with SHA-256 as the hash function used in step two.
    1. Optionally, inspect |x5c| and consult externally provided knowledge to determine whether |attStmt| conveys a [=Basic=] or
        [=AttCA=] attestation.
    1. If successful, return implementation-specific values representing [=attestation type=] [=Basic=], [=AttCA=] or uncertainty,
        and [=attestation trust path=] |x5c|.

## None Attestation Statement Format ## {#sctn-none-attestation}

The none attestation statement format is used to replace any [=authenticator=]-provided [=attestation statement=] when a [=[WRP]=] indicates it does not wish to receive attestation information, see  [[#enum-attestation-convey]].

The [=authenticator=] MAY also directly generate attestation statements of this format
if the [=authenticator=] does not support [=attestation=].

: Attestation statement format identifier
:: none

: Attestation types supported
:: [=None=]

: Syntax
:: The syntax of a none attestation statement is defined as follows:

    ```
    $$attStmtType //= (
                          fmt: "none",
                          attStmt: emptyMap
                      )

    emptyMap = {}
    ```

: Signing procedure
:: Return the fixed attestation statement defined above.

: Verification procedure
:: Return implementation-specific values representing [=attestation type=] [=None=] and an empty [=attestation trust path=].

## Apple Anonymous Attestation Statement Format ## {#sctn-apple-anonymous-attestation}

This attestation statement format is exclusively used by Apple for certain types of Apple devices that support WebAuthn.

: Attestation statement format identifier
:: apple

: Attestation types supported
:: [=Anonymization CA=]

: Syntax
:: The syntax of an Apple attestation statement is defined as follows:

    ```
    $$attStmtType //= (
                          fmt: "apple",
                          attStmt: appleStmtFormat
                      )

    appleStmtFormat = {
                          x5c: [ credCert: bytes, * (caCert: bytes) ]
                      }
    ```

    The semantics of the above fields are as follows:

    : x5c
    :: |credCert| followed by its certificate chain, each encoded in X.509 format.

    : credCert
    :: The credential public key certificate used for attestation, encoded in X.509 format.

: Signing procedure
::
    1. Let |authenticatorData| denote the authenticator data for the attestation, and let |clientDataHash| denote the [=hash of the serialized client data=].
    2. Concatenate |authenticatorData| and |clientDataHash| to form |nonceToHash|.
    3. Perform SHA-256 hash of |nonceToHash| to produce |nonce|.
    4. Let Apple anonymous attestation CA generate an X.509 certificate for the [=credential public key=] and include the |nonce| as a certificate extension with OID `1.2.840.113635.100.8.2`. |credCert| denotes this certificate. The |credCert| thus serves as a proof of the attestation, and the included |nonce| proves the attestation is live. In addition to that, the |nonce| also protects the integrity of the |authenticatorData| and [=client data=].
    5. Set |x5c| to |credCert| followed by its certificate chain.

: Verification procedure
:: Given the verification procedure inputs |attStmt|, |authenticatorData| and |clientDataHash|, the verification procedure is as follows:
    1. Verify that |attStmt| is valid CBOR conforming to the syntax defined above and perform CBOR decoding on it to extract the contained fields.
    2. Concatenate |authenticatorData| and |clientDataHash| to form |nonceToHash|.
    3. Perform SHA-256 hash of |nonceToHash| to produce |nonce|.
    4. Verify that |nonce| equals the value of the extension with OID `1.2.840.113635.100.8.2` in |credCert|.
    5. Verify that the [=credential public key=] equals the Subject Public Key of |credCert|.
    6. If successful, return implementation-specific values representing attestation type [=Anonymization CA=] and attestation trust path |x5c|.

## Compound Attestation Statement Format ## {#sctn-compound-attestation}

The "compound" attestation statement format is used to pass multiple, self-contained attestation statements in a single ceremony.


: Attestation statement format identifier
:: compound

: Attestation types supported
:: Any. See [[#sctn-attestation-types]].

: Syntax
:: The syntax of a compound attestation statement is defined as follows:

    ```
    $$attStmtType //= (
                          fmt: "compound",
                          attStmt: [2* nonCompoundAttStmt]
                      )

    nonCompoundAttStmt = { $$attStmtType } .within { fmt: text .ne "compound", * any => any }
    ```

: Signing procedure
:: Not applicable

: Verification procedure
:: Given the [=verification procedure inputs=] |attStmt|, |authenticatorData| and |clientDataHash|, the [=verification procedure=] is
    as follows:
    1. [=list/For each=] |subStmt| of |attStmt|, evaluate the [=verification procedure=]
        corresponding to the [=attestation statement format identifier=] <code>|subStmt|.fmt</code>
        with [=verification procedure inputs=] |subStmt|, |authenticatorData| and |clientDataHash|.

        If validation fails for one or more |subStmt|, decide the appropriate result based on [=[RP]=] policy.

    2. If sufficiently many (as determined by [=[RP]=] policy) [=list/items=] of |attStmt| verify successfully,
        return implementation-specific values representing any combination of outputs from successful [=verification procedures=].


# <dfn>WebAuthn Extensions</dfn> # {#sctn-extensions}

The mechanism for generating [=public key credentials=], as well as requesting and generating Authentication assertions, as
defined in [[#sctn-api]], can be extended to suit particular use cases. Each case is addressed by defining a <dfn>registration
extension</dfn> and/or an <dfn>authentication extension</dfn>.

Every extension is a <dfn>client extension</dfn>, meaning that the extension involves communication with and processing by the
client.
[=Client extensions=] define the following steps and data:

- {{CredentialsContainer/create()|navigator.credentials.create()}} extension request parameters and response values for [=registration extensions=].

- {{CredentialsContainer/get()|navigator.credentials.get()}} extension request parameters and response values for [=authentication extensions=].

- [=Client extension processing=] for [=registration extensions=] and [=authentication extensions=].

When creating a [=public key credential=] or requesting an [=authentication assertion=], a [=[WRP]=] can request the use of a set
of extensions. These extensions will be invoked during the requested operation if they are supported by the client and/or the
[=[WAA]=]. The [=[RP]=] sends the [=client extension input=] for each extension in the {{CredentialsContainer/get()}} call
(for [=authentication extensions=]) or {{CredentialsContainer/create()}} call (for [=registration extensions=]) to the [=client=].
The [=client=] performs [=client extension processing=] for each extension that the [=client platform=] supports, and augments the
[=client data=] as specified by each extension, by including the [=extension identifier=] and [=client extension output=]
values.

An extension can also be an <dfn>authenticator extension</dfn>, meaning that the extension involves communication with and
processing by the authenticator. [=Authenticator extensions=] define the following steps and data:

- [=authenticatorMakeCredential=] extension request parameters and response values for [=registration extensions=].

- [=authenticatorGetAssertion=] extension request parameters and response values for [=authentication extensions=].

- [=Authenticator extension processing=] for [=registration extensions=] and [=authentication extensions=].

For [=authenticator extensions=], as part of the [=client extension processing=], the client also creates the [=CBOR=]
[=authenticator extension input=] value for each extension (often based on the corresponding [=client extension input=] value),
and passes them to the authenticator in the {{CredentialsContainer/create()}} call (for [=registration extensions=]) or the
{{CredentialsContainer/get()}} call (for [=authentication extensions=]). These [=authenticator extension input=] values are
represented in [=CBOR=] and passed as name-value pairs, with the [=extension identifier=] as the name, and the corresponding
[=authenticator extension input=] as the value. The authenticator, in turn, performs additional processing for the extensions
that it supports, and returns the [=CBOR=] [=authenticator extension output=] for each as specified by the extension.
Since [=authenticator extension output=] is returned as part of the signed [=authenticator data=], authenticator extensions
MAY also specify an [=unsigned extension output=], e.g. for cases where an output itself depends on [=authenticator data=].
Part of the [=client extension processing=] for [=authenticator extensions=] is to use the [=authenticator extension output=]
and [=unsigned extension output=] as an input to creating the [=client extension output=].

All [=WebAuthn Extensions=] are OPTIONAL for both clients and authenticators. Thus, any extensions requested by a [=[RP]=] MAY be
ignored by the client browser or OS and not passed to the authenticator at all, or they MAY be ignored by the authenticator.
Ignoring an extension is never considered a failure in WebAuthn API processing, so when [=[RPS]=] include extensions with any
API calls, they MUST be prepared to handle cases where some or all of those extensions are ignored.

All [=WebAuthn Extensions=] MUST be defined in such a way that lack of support for them by the [=client=] or [=authenticator=]
does not endanger the user's security or privacy.
For instance, if an extension requires client processing, it could be defined in a manner that ensures
that a naïve pass-through that simply transcodes [=client extension inputs=] from JSON to CBOR
will produce a semantically invalid [=authenticator extension input=] value, resulting in the extension
being ignored by the authenticator. Since all extensions are OPTIONAL, this will not cause a functional failure in the API
operation.

The IANA "WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]] can be consulted
for an up-to-date list of registered [=WebAuthn Extensions=].

## Extension Identifiers ## {#sctn-extension-id}

Extensions are identified by a string, called an <dfn>extension identifier</dfn>, chosen by the extension author.

Extension identifiers SHOULD be registered in the
IANA "WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]].
All registered extension identifiers are unique amongst themselves as a matter of course.

Unregistered extension identifiers SHOULD aim to be globally unique, e.g., by including the defining entity such as
`myCompany_extension`.

All extension identifiers MUST be a maximum of 32 octets in length and MUST consist only of printable USASCII characters,
excluding backslash and doublequote, i.e., VCHAR as defined in [[!RFC5234]] but without %x22 and %x5c. Implementations MUST
match WebAuthn extension identifiers in a case-sensitive fashion.

Extensions that may exist in multiple versions should take care to include a version in their identifier. In effect, different
versions are thus treated as different extensions, e.g., `myCompany_extension_01`

[[#sctn-defined-extensions]] defines an additional set of extensions and their identifiers.
See the IANA "WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]]
for an up-to-date list of registered WebAuthn Extension Identifiers.


## Defining Extensions ## {#sctn-extension-specification}

A definition of an extension MUST specify an [=extension identifier=], a [=client extension input=] argument
to be sent via the {{CredentialsContainer/get()}} or {{CredentialsContainer/create()}} call,
the [=client extension processing=] rules, and a [=client extension output=] value.
If the extension communicates with the authenticator (meaning it is an [=authenticator extension=]),
it MUST also specify the [=CBOR=] [=authenticator extension input=] argument
sent via the [=authenticatorGetAssertion=] or [=authenticatorMakeCredential=] call,
the [=authenticator extension processing=] rules, and the [=CBOR=] [=authenticator extension output=] value.
Extensions MAY specify [=unsigned extension outputs=].

Any [=client extension=] that is processed by the client MUST return a [=client extension output=] value so that the [=[WRP]=]
knows that the extension was honored by the client. Similarly, any extension that requires authenticator processing MUST return
an [=authenticator extension output=] to let the [=[RP]=] know that the extension was honored by the authenticator. If an
extension does not otherwise require any result values, it SHOULD be defined as returning a JSON Boolean [=client extension
output=] result, set to [TRUE] to signify that the extension was understood and processed. Likewise, any [=authenticator
extension=] that does not otherwise require any result values MUST return a value and SHOULD return a CBOR Boolean
[=authenticator extension output=] result, set to [TRUE] to signify that the extension was understood and processed.


## Extending Request Parameters ## {#sctn-extension-request-parameters}

An extension defines one or two request arguments. The <dfn>client extension input</dfn>,
which is a value that can be encoded in JSON, is passed from the [=[WRP]=] to the client
in the {{CredentialsContainer/get()}} or {{CredentialsContainer/create()}} call,
while the [=CBOR=] <dfn>authenticator extension input</dfn> is
passed from the client to the authenticator for [=authenticator extensions=] during the processing of these calls.

A [=[RP]=] simultaneously requests the use of an extension and sets its [=client extension input=] by including an entry in the
{{PublicKeyCredentialCreationOptions/extensions}} option to the {{CredentialsContainer/create()}} or {{CredentialsContainer/get()}} call.
The entry key is the [=extension identifier=] and the value is the [=client extension input=].

Note: Other documents have specified extensions where the extension input does not always use the [=extension identifier=]
as the entry key.
The above convention still applies to new extensions.

<xmp class="example" highlight="js">
    var assertionPromise = navigator.credentials.get({
        publicKey: {
            // Other members omitted for brevity
            extensions: {
                // An "entry key" identifying the "webauthnExample_foobar" extension,
                // whose value is a map with two input parameters:
                "webauthnExample_foobar": {
                  foo: 42,
                  bar: "barfoo"
                }
            }
        }
    });
</xmp>

Extension definitions MUST specify the valid values for their [=client extension input=]. Clients SHOULD ignore extensions with
an invalid [=client extension input=]. If an extension does not require any parameters from the [=[RP]=], it SHOULD be defined
as taking a Boolean client argument, set to [TRUE] to signify that the extension is requested by the [=[RP]=].

Extensions that only affect client processing need not specify [=authenticator extension input=]. Extensions that have
authenticator processing MUST specify the method of computing the [=authenticator extension input=] from the [=client extension
input=],
and MUST define extensions for the [=CDDL=] types
<code>[[#iface-authentication-extensions-authenticator-inputs|AuthenticationExtensionsAuthenticatorInputs]]</code>
and <code>[[#iface-authentication-extensions-authenticator-outputs|AuthenticationExtensionsAuthenticatorOutputs]]</code>
by defining an additional choice for the `$$extensionInput` and `$$extensionOutput` [=group sockets=]
using the [=extension identifier=] as the entry key.
Extensions that do not require input parameters, and are thus defined as taking a Boolean [=client extension input=]
value set to [TRUE],
SHOULD define the [=authenticator extension input=] also as the constant Boolean value [TRUE] (CBOR major type
7, value 21).

The following example defines that an extension with [=extension identifier|identifier=] `webauthnExample_foobar`
takes an unsigned integer as [=authenticator extension input=],
and returns an array of at least one byte string as [=authenticator extension output=]:

<xmp class="example" highlight="cddl">
    $$extensionInput //= (
      webauthnExample_foobar: uint
    )
    $$extensionOutput //= (
      webauthnExample_foobar: [+ bytes]
    )
</xmp>

Because some authenticators communicate over low-bandwidth links such as Bluetooth Low-Energy or NFC,
extensions SHOULD aim to define authenticator arguments that are as small as possible.


## <dfn>Client Extension Processing</dfn> ## {#sctn-client-extension-processing}

Extensions MAY define additional processing requirements on the [=client=] during the creation of credentials or the
generation of an assertion. The [=client extension input=] for the extension is used as an input to this client processing.
For each supported [=client extension=], the client adds an entry to the |clientExtensions|  [=map=] with the
[=extension identifier=] as the key, and the extension's [=client extension input=] as the value.

Likewise, the [=client extension outputs=] are represented as a dictionary in the result of {{PublicKeyCredential/getClientExtensionResults()}}
with [=extension identifiers=] as keys, and the <dfn>client extension output</dfn> value of each extension as the value.
Like the [=client extension input=], the [=client extension output=] is a value that can be encoded in JSON.
There MUST NOT be any values returned for ignored extensions.

Extensions that require authenticator processing MUST define
the process by which the [=client extension input=] can be used to determine the [=CBOR=] [=authenticator extension input=] and
the process by which the [=CBOR=] [=authenticator extension output=], and the [=unsigned extension output=] if used, can be
used to determine the [=client extension output=].

## <dfn>Authenticator Extension Processing</dfn> ## {#sctn-authenticator-extension-processing}

The [=CBOR=] [=authenticator extension input=] value of each processed [=authenticator extension=] is included in the |extensions|
parameter of the [=authenticatorMakeCredential=] and [=authenticatorGetAssertion=] operations. The |extensions| parameter is a
[=CBOR=] map where each key is an [=extension identifier=] and the corresponding value is the [=authenticator extension input=]
for that extension.

Likewise, the extension output is represented in the [=authData/extensions=] part of the [=authenticator data=]. The
[=authData/extensions=] part of the [=authenticator data=] is a CBOR map where each key is an [=extension identifier=]
and the corresponding value is the <dfn>authenticator extension output</dfn> for that extension.

<dfn>Unsigned extension outputs</dfn> are represented independently from [=authenticator data=] and returned by authenticators
as a separate map, keyed with the same [=extension identifier=]. This map only contains entries for authenticator
extensions that make use of unsigned outputs. Unsigned outputs are useful when extensions output a signature over
the [=authenticator data=] (because otherwise a signature would have to sign over itself, which isn't possible) or when
some extension outputs should not be sent to the [=[RP]=].

Note: In [[!FIDO-CTAP]] [=unsigned extension outputs=] are returned as a CBOR map in a top-level field named
`unsignedExtensionOutputs` from both [=authenticatorMakeCredential=] and [=authenticatorGetAssertion=].

For each supported extension, the [=authenticator extension processing=] rule for that extension is used create the
[=authenticator extension output=], and [=unsigned extension output=] if used, from the [=authenticator extension input=]
and possibly also other inputs.
There MUST NOT be any values returned for ignored extensions.


# Defined Extensions # {#sctn-defined-extensions}

This section and its subsections define an additional set of extensions to be registered in the
IANA "WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]].
These MAY be implemented by user agents targeting broad interoperability.

## Client Extensions ## {#sctn-defined-client-extensions}

This section defines extensions that are only [=client extensions=].

### FIDO <dfn>AppID</dfn> Extension (appid) ### {#sctn-appid-extension}

This extension allows [=[WRPS]=] that have previously registered a
credential using the legacy FIDO U2F JavaScript API [[FIDOU2FJavaScriptAPI]] to request an [=assertion=]. The
FIDO APIs use an alternative identifier for [=[RPS]=] called an |AppID|
[[!FIDO-APPID]], and any credentials created using those APIs will be [=scoped=] to
that identifier. Without this extension, they would need to be re-registered in
order to be [=scoped=] to an [=RP ID=].

In addition to setting the {{AuthenticationExtensionsClientInputs/appid}} extension input,
using this extension requires some additional processing by the [=[RP]=]
in order to allow users to [=authentication|authenticate=] using their registered U2F credentials:

 1. List the desired U2F credentials in the {{PublicKeyCredentialRequestOptions/allowCredentials}} option
     of the {{CredentialsContainer/get()}} method:

     - Set the {{PublicKeyCredentialDescriptor/type}} members to {{PublicKeyCredentialType/public-key}}.
     - Set the {{PublicKeyCredentialDescriptor/id}} members to the respective U2F key handles of the desired credentials. Note that U2F key handles commonly use [=base64url encoding=] but must be decoded to their binary form when used in {{PublicKeyCredentialDescriptor/id}}.

     {{PublicKeyCredentialRequestOptions/allowCredentials}} MAY contain a mixture
     of both WebAuthn [=credential IDs=] and U2F key handles;
     stating the {{AuthenticationExtensionsClientInputs/appid}} via this extension
     does not prevent the user from using a WebAuthn-registered credential
     scoped to the [=RP ID=] stated in {{PublicKeyCredentialRequestOptions/rpId}}.

 1. When [verifying the assertion](#rp-op-verifying-assertion-step-rpid-hash), expect that the <code>[=rpIdHash=]</code>
     MAY be the hash of the |AppID| instead of the [=RP ID=].

This extension does not allow FIDO-compatible credentials to be created. Thus,
credentials created with WebAuthn are not backwards compatible with the FIDO
JavaScript APIs.

Note: {{AuthenticationExtensionsClientInputs/appid}} should be set to the AppID
that the [=[RP]=] *previously* used in the legacy FIDO APIs.
This might not be the same as the result of translating the [=[RP]=]'s WebAuthn [=RP ID=] to the AppID format,
e.g., the previously used AppID may have been "https://accounts.example.com"
but the currently used [=RP ID=] might be "example.com".

: Extension identifier
:: `appid`

: Operation applicability
:: [=authentication extension|Authentication=]

: Client extension input
:: A single DOMString specifying a FIDO |AppID|.
    <xmp class="idl">
    partial dictionary AuthenticationExtensionsClientInputs {
      DOMString appid;
    };
    partial dictionary AuthenticationExtensionsClientInputsJSON {
      DOMString appid;
    };
    </xmp>

: Client extension processing
::  1. Let |facetId| be the result of passing the caller's [=origin=] to the
        FIDO algorithm for [=determining the FacetID of a calling application=].
    1. Let |appId| be the extension input.
    1. Pass |facetId| and |appId| to the FIDO algorithm for [=determining if a
        caller's FacetID is authorized for an AppID=]. If that algorithm rejects
        |appId| then return a "{{SecurityError}}" {{DOMException}}.
    1. When [building allowCredentialDescriptorList](#allowCredentialDescriptorListCreation),
        if a U2F authenticator indicates that a credential is inapplicable (i.e. by
        returning `SW_WRONG_DATA`) then the client MUST retry with the U2F application
        parameter set to the SHA-256 hash of |appId|. If this results in an applicable
        credential, the client MUST include the credential in
        <var ignore>allowCredentialDescriptorList</var>. The value of |appId| then replaces the `rpId`
        parameter of [=authenticatorGetAssertion=].
    1. Let |output| be the Boolean value [FALSE].
    1. When [creating assertionCreationData](#assertionCreationDataCreation),
        if the [=assertion=] was created by a U2F authenticator with the U2F application parameter set to the SHA-256 hash of |appId|
        instead of the SHA-256 hash of the [=RP ID=], set |output| to [TRUE].

Note: In practice, several implementations do not implement steps four and onward of the
algorithm for [=determining if a caller's FacetID is authorized for an AppID=].
Instead, in step three, the comparison on the host is relaxed to accept hosts on the
[=same site=].

: Client extension output
:: Returns the value of |output|. If true, the |AppID| was used and thus, when [verifying the assertion](#rp-op-verifying-assertion-step-rpid-hash), the [=[RP]=] MUST expect the <code>[=rpIdHash=]</code> to be the hash of the |AppID|, not the [=RP ID=].

    <xmp class="idl">
    partial dictionary AuthenticationExtensionsClientOutputs {
      boolean appid;
    };
    partial dictionary AuthenticationExtensionsClientOutputsJSON {
      boolean appid;
    };
    </xmp>

: Authenticator extension input
:: None.

: Authenticator extension processing
:: None.

: Authenticator extension output
:: None.

### FIDO AppID Exclusion Extension (appidExclude) ### {#sctn-appid-exclude-extension}

This registration extension allows [=[WRPS]=] to exclude authenticators that contain specified credentials that were created with the legacy FIDO U2F JavaScript API [[FIDOU2FJavaScriptAPI]].

During a transition from the FIDO U2F JavaScript API, a [=[RP]=] may have a population of users with legacy credentials already registered. The [appid](#sctn-appid-extension) extension allows the sign-in flow to be transitioned smoothly but, when transitioning the registration flow, the [excludeCredentials](#dom-publickeycredentialcreationoptions-excludecredentials) field will not be effective in excluding authenticators with legacy credentials because its contents are taken to be WebAuthn credentials. This extension directs [=client platforms=] to consider the contents of [excludeCredentials](#dom-publickeycredentialcreationoptions-excludecredentials) as both WebAuthn and legacy FIDO credentials. Note that U2F key handles commonly use [=base64url encoding=] but must be decoded to their binary form when used in [excludeCredentials](#dom-publickeycredentialcreationoptions-excludecredentials).


: Extension identifier
:: `appidExclude`

: Operation applicability
:: [=registration extension|Registration=]

: Client extension input
:: A single DOMString specifying a FIDO |AppID|.
    <xmp class="idl">
    partial dictionary AuthenticationExtensionsClientInputs {
      DOMString appidExclude;
    };
    partial dictionary AuthenticationExtensionsClientInputsJSON {
      DOMString appidExclude;
    };
    </xmp>

: Client extension processing
:: When [[#sctn-createCredential|creating a new credential]]:
        1. Just after [establishing the RP ID](#CreateCred-DetermineRpId) perform these steps:
            1. Let |facetId| be the result of passing the caller's [=origin=] to the FIDO algorithm
                for [=determining the FacetID of a calling application=].
            1. Let |appId| be the value of the extension input {{AuthenticationExtensionsClientInputs/appidExclude}}.
            1. Pass |facetId| and |appId| to the FIDO algorithm for [=determining if a caller's
                FacetID is authorized for an AppID=]. If the latter algorithm rejects |appId| then
                return a "{{SecurityError}}" {{DOMException}} and terminate the
                [creating a new credential](#sctn-createCredential) algorithm as well as these steps.

                Note: In practice, several implementations do not implement steps four and onward of the algorithm for [=determining if a caller's FacetID is authorized for an AppID=]. Instead, in step three, the comparison on the host is relaxed to accept hosts on the [=same site=].

            1. Otherwise, continue with normal processing.

        1. Just prior to [invoking authenticatorMakeCredential](#CreateCred-InvokeAuthnrMakeCred) perform these steps:
            1. If |authenticator| supports the U2F protocol [[!FIDO-U2F-Message-Formats]], then [=list/for each=]
                [credential descriptor](#dictdef-publickeycredentialdescriptor) |C| in |excludeCredentialDescriptorList|:
                1. Check whether |C| was created using U2F on |authenticator| by sending a
                    `U2F_AUTHENTICATE` message to |authenticator|
                    whose "five parts" are set to the following values:

                        :   |control byte|
                        ::  `0x07` ("check-only")

                        :   <var ignore>challenge parameter</var>
                        ::  32 random bytes

                        :   <var ignore>application parameter</var>
                        ::  SHA-256 hash of |appId|

                        :   <var ignore>key handle length</var>
                        ::  The length of <code>|C|.{{PublicKeyCredentialDescriptor/id}}</code> (in bytes)

                        :   <var ignore>key handle</var>
                        ::  The value of <code>|C|.{{PublicKeyCredentialDescriptor/id}}</code>, i.e., the [=credential id=].

                1. If |authenticator| responds with `message:error:test-of-user-presence-required` (i.e., success):
                    cease normal processing of this |authenticator| and indicate in a platform-specific manner
                    that the authenticator is inapplicable. For example, this could be in the form of UI, or
                    could involve requesting [=user consent=] from |authenticator| and, upon receipt, treating
                    it as if the authenticator had returned {{InvalidStateError}}. Requesting [=user consent=]
                    can be accomplished by sending another `U2F_AUTHENTICATE` message to |authenticator| as
                    above except for setting |control byte| to `0x03` ("enforce-user-presence-and-sign"),
                    and ignoring the response.

            1. Continue with normal processing.

: Client extension output
:: Returns the value [TRUE] to indicate to the [=[RP]=] that the extension was acted upon.
    <xmp class="idl">
    partial dictionary AuthenticationExtensionsClientOutputs {
      boolean appidExclude;
    };
    partial dictionary AuthenticationExtensionsClientOutputsJSON {
      boolean appidExclude;
    };
    </xmp>

: Authenticator extension input
:: None.

: Authenticator extension processing
:: None.

: Authenticator extension output
:: None.


### Credential Properties Extension (<dfn>credProps</dfn>) ### {#sctn-authenticator-credential-properties-extension}

This [=client extension|client=] [=registration extension=] facilitates reporting certain [=credential properties=] known by the [=client=] to the requesting [=[WRP]=] upon creation of a [=public key credential source=] as a result of a [=registration ceremony=].

At this time, one [=credential property=] is defined: the [=client-side discoverable credential property=].


: Extension identifier
:: `credProps`

: Operation applicability
:: [=registration extension|Registration=]

: Client extension input
:: The Boolean value [TRUE] to indicate that this extension is requested by the [=[RP]=].
    <xmp class="idl">
    partial dictionary AuthenticationExtensionsClientInputs {
        boolean credProps;
    };
    partial dictionary AuthenticationExtensionsClientInputsJSON {
        boolean credProps;
    };
    </xmp>

: Client extension processing
::  Set {{CredentialPropertiesOutput/rk}} to the value of the |requireResidentKey| parameter that was used in the
    <a href='#CreateCred-InvokeAuthnrMakeCred'>invocation</a> of the [=authenticatorMakeCredential=]
    operation.

: Client extension output
:: [=map/Set=] <code>[=credentialCreationData/clientExtensionResults=]["{{AuthenticationExtensionsClientOutputs/credProps}}"]["rk"]</code> to the value of the |requireResidentKey| parameter that was used in the <a href='#CreateCred-InvokeAuthnrMakeCred'>invocation</a> of the [=authenticatorMakeCredential=] operation.

    <xmp class="idl">
    dictionary CredentialPropertiesOutput {
        boolean rk;
    };

    partial dictionary AuthenticationExtensionsClientOutputs {
        CredentialPropertiesOutput credProps;
    };
    partial dictionary AuthenticationExtensionsClientOutputsJSON {
        CredentialPropertiesOutput credProps;
    };
    </xmp>

    <div dfn-type="dict-member" dfn-for="CredentialPropertiesOutput">
        :   <dfn>rk</dfn>
        ::  This OPTIONAL property, known abstractly as the <dfn dfn-type="dfn">client-side discoverable credential property</dfn>
            or as the <dfn dfn-type="dfn">resident key credential property</dfn>,
            is a Boolean value indicating whether the {{PublicKeyCredential}} returned as a result of a [=registration ceremony=]
            is a [=client-side discoverable credential=].
            If {{rk}} is [TRUE], the credential is a [=discoverable credential=].
            If {{rk}} is [FALSE], the credential is a [=server-side credential=].
            If {{rk}} is not present, it is not known whether the credential is a [=discoverable credential=] or a [=server-side credential=].

            Note: Some [=authenticators=] create [=discoverable credentials=] even when not requested by the [=client platform=]. Because of this, [=client platforms=] may be forced to omit the {{rk}} property because they lack the assurance to be able to set it to [FALSE]. [=[RPS]=] should assume that, if the `credProps` extension is supported, then [=client platforms=] will endeavour to populate the {{rk}} property. Therefore a missing {{rk}} indicates that the created credential is most likely a [=non-discoverable credential=].
    </div>


: Authenticator extension input
:: None.

: Authenticator extension processing
:: None.

: Authenticator extension output
:: None.

### Pseudo-random function extension (<dfn>prf</dfn>) ### {#prf-extension}

This [=client extension|client=] [=registration extension=] and [=authentication extension=] allows a [=[RP]=] to evaluate outputs from a pseudo-random function (PRF) associated with a [=credential=]. The PRFs provided by this extension map from {{BufferSource}}s of any length to 32-byte {{BufferSource}}s.

As a motivating example, PRF outputs could be used as symmetric keys to encrypt user data. Such encrypted data would be inaccessible without the ability to get assertions from the associated [=credential=]. By using the provision below to evaluate the PRF at two inputs in a single [=assertion=] operation, the encryption key could be periodically rotated during [=assertions=] by choosing a fresh, random input and reencrypting under the new output. If the evaluation inputs are unpredictable then even an attacker who could satisfy [=user verification=], and who had time-limited access to the authenticator, could not learn the encryption key without also knowing the correct PRF input.

This extension is modeled on top of the [[FIDO-CTAP]] `hmac-secret` extension, but can also be implemented by other means.
It is a separate [=client extension=] because `hmac-secret` requires that inputs and outputs be encrypted
in a manner that only the user agent can perform,
and to provide separation between uses by WebAuthn and any uses by the underlying platform.
This separation is achieved by hashing the provided PRF inputs with a context string
to prevent evaluation of the PRFs for arbitrary inputs.

The `hmac-secret` extension provides two PRFs per credential: one which is used for requests where [=user verification=] is performed and another for all other requests. This extension only exposes a single PRF per credential and, when implementing on top of `hmac-secret`, that PRF MUST be the one used for when [=user verification=] is performed. This overrides the {{UserVerificationRequirement}} if necessary.

This extension MAY be implemented for [=authenticators=] that do not use [[FIDO-CTAP]].
The interface for this between [=client=] and [=authenticator=],
and the construction of the PRF by the authenticator, is only abstractly specified.

Note: Implementing on top of `hmac-secret` causes [=authenticator extension outputs=] that are not present otherwise.
These outputs are encrypted and cannot be used by the [=[RP]=],
but also cannot be deleted by the client since the [=authenticator data=] is signed.


: Extension identifier
:: `prf`

: Operation applicability
:: [=registration extension|Registration=] and [=authentication extension|authentication=]

: Client extension input
::  <xmp class="idl">
    dictionary AuthenticationExtensionsPRFValues {
        required BufferSource first;
        BufferSource second;
    };
    dictionary AuthenticationExtensionsPRFValuesJSON {
        required Base64URLString first;
        Base64URLString second;
    };

    dictionary AuthenticationExtensionsPRFInputs {
        AuthenticationExtensionsPRFValues eval;
        record<DOMString, AuthenticationExtensionsPRFValues> evalByCredential;
    };
    dictionary AuthenticationExtensionsPRFInputsJSON {
        AuthenticationExtensionsPRFValuesJSON eval;
        record<DOMString, AuthenticationExtensionsPRFValuesJSON> evalByCredential;
    };

    partial dictionary AuthenticationExtensionsClientInputs {
        AuthenticationExtensionsPRFInputs prf;
    };
    partial dictionary AuthenticationExtensionsClientInputsJSON {
        AuthenticationExtensionsPRFInputsJSON prf;
    };
    </xmp>

    <div dfn-type="dict-member" dfn-for="AuthenticationExtensionsPRFInputs">
        :   <dfn>eval</dfn>
        ::  One or two inputs on which to evaluate PRF. Not all [=authenticators=] support evaluating the PRFs during credential creation so outputs may, or may not, be provided. If not, then an [=assertion=] is needed in order to obtain the outputs.

        :   <dfn>evalByCredential</dfn>
        ::  A record mapping [=base64url encoding|base64url encoded=] [=credential IDs=] to PRF inputs to evaluate for that credential. Only applicable during [=assertions=] when {{PublicKeyCredentialRequestOptions/allowCredentials}} is not empty.
    </div>

: Client extension processing ([=registration extension|registration=])
::
       1. If {{AuthenticationExtensionsPRFInputs/evalByCredential}} is present, return a {{DOMException}} whose name is “{{NotSupportedError}}”.
       1. If {{AuthenticationExtensionsPRFInputs/eval}} is present:
            - Let |salt1| be the value of <code>SHA-256(UTF8Encode("WebAuthn PRF") || 0x00 || {{AuthenticationExtensionsPRFInputs/eval}}.{{AuthenticationExtensionsPRFValues/first}})</code>.
            - If <code>{{AuthenticationExtensionsPRFInputs/eval}}.{{AuthenticationExtensionsPRFValues/second}}</code> is present,
                let |salt2| be the value of <code>SHA-256(UTF8Encode("WebAuthn PRF") || 0x00 || {{AuthenticationExtensionsPRFInputs/eval}}.{{AuthenticationExtensionsPRFValues/second}})</code>.

       1. If the authenticator supports the CTAP2 `hmac-secret` extension [[FIDO-CTAP]]:
          1. Set `hmac-secret` to [TRUE] in the authenticator extensions input.
          1. If |salt1| is defined and a future extension to [[FIDO-CTAP]] permits evaluation of the PRF at creation time,
              configure `hmac-secret` inputs accordingly using the values of |salt1| and, if defined, |salt2|.
          1. Set {{AuthenticationExtensionsPRFOutputs/enabled}} to the value of `hmac-secret` in the authenticator extensions output. If not present, set {{AuthenticationExtensionsPRFOutputs/enabled}} to [FALSE].
          1. Set {{AuthenticationExtensionsPRFOutputs/results}} to the decrypted PRF result(s), if any.

       1. If the authenticator does not support the CTAP2 `hmac-secret` extension [[FIDO-CTAP]],
            but does support some other implementation compatible with the abstract authenticator processing defined below:
          1. Set {{AuthenticationExtensionsPRFOutputs/enabled}} to [TRUE].
          1. If |salt1| is defined, use some unspecified mechanism to convey |salt1| and,
              if defined, |salt2| to the authenticator as PRF inputs, in that order.
          1. Use some unspecified mechanism to receive the PRF outputs from the authenticator.
              Set <code>{{AuthenticationExtensionsPRFOutputs/results}}</code> to the evaluation results, if any.

: Client extension processing ([=authentication extension|authentication=])
::
      1. If {{AuthenticationExtensionsPRFInputs/evalByCredential}} is not empty but {{PublicKeyCredentialRequestOptions/allowCredentials}} is empty, return a {{DOMException}} whose name is “{{NotSupportedError}}”.
      1. If any [=map/key=] in {{AuthenticationExtensionsPRFInputs/evalByCredential}} is the empty string, or is not a valid [=base64url encoding=], or does not equal the {{PublicKeyCredentialDescriptor/id}} of some element of {{PublicKeyCredentialRequestOptions/allowCredentials}} after performing [=base64url encoding|base64url decoding=], then return a {{DOMException}} whose name is “{{SyntaxError}}”.
      1. Initialize the {{AuthenticationExtensionsClientOutputs/prf}} extension output to an empty dictionary.
      1. Let |ev| be null, and try to find any applicable PRF input(s):
          1. If {{AuthenticationExtensionsPRFInputs/evalByCredential}} is present and [=map/exists|contains=] an [=map/entry=] whose [=map/key=] is the [=base64url encoding=] of the [=credential ID=] that will be returned, let |ev| be the [=map/value=] of that entry.
          1. If |ev| is null and {{AuthenticationExtensionsPRFInputs/eval}} is present, then let |ev| be the value of {{AuthenticationExtensionsPRFInputs/eval}}.
      1. If |ev| is not null:
          1. Let |salt1| be the value of <code>SHA-256(UTF8Encode("WebAuthn PRF") || 0x00 || |ev|.{{AuthenticationExtensionsPRFValues/first}})</code>.
          1. If <code>|ev|.{{AuthenticationExtensionsPRFValues/second}}</code> is present, let |salt2| be the value of <code>SHA-256(UTF8Encode("WebAuthn PRF") || 0x00 || |ev|.{{AuthenticationExtensionsPRFValues/second}})</code>.
          1. If the authenticator supports the CTAP2 `hmac-secret` extension [[FIDO-CTAP]]:
              1. Send an `hmac-secret` extension to the [=authenticator=] using the values of |salt1| and, if set, |salt2| as the parameters of the same name in that process.
              1. Decrypt the extension result and set {{AuthenticationExtensionsPRFOutputs/results}} to the PRF result(s), if any.
          1. If the authenticator does not support the CTAP2 `hmac-secret` extension [[FIDO-CTAP]],
              but does support some other implementation compatible with the abstract authenticator processing defined below:
              1. Use some unspecified mechanism to convey |salt1| and, if defined, |salt2| to the authenticator as PRF inputs, in that order.
              1. Use some unspecified mechanism to receive the PRF outputs from the authenticator as an {{AuthenticationExtensionsPRFValues}} value |results|.
                  Set <code>{{AuthenticationExtensionsPRFOutputs/results}}</code> to |results|.

: Authenticator extension input / output
:: [=prf|This extension=] is abstract over the authenticator implementation,
    using either the [[FIDO-CTAP]] `hmac-secret` extension or an unspecified interface for communication between the client and authenticator.
    It thus does not specify a CBOR interface for inputs and outputs.

: Authenticator extension processing
:: [=Authenticators=] that support the [[FIDO-CTAP]] `hmac-secret` extension implement authenticator processing as defined in that extension.

    [=Authenticators=] that do not support the [[FIDO-CTAP]] `hmac-secret` extension
    MAY instead implement the following abstract procedure:

    1. Let |PRF| be the pseudo-random function associated with the current [=credential=],
        or initialize the association if uninitialized:

        Let |PRF| be a pseudo-random function whose outputs are exactly 32 bytes long,
        selected uniformly at random from a set of at least 2<sup>256</sup> such functions.
        The choice of |PRF| MUST be independent of the state of [=user verification=].
        The selected |PRF| SHOULD NOT be used for other purposes than implementing this extension.
        Associate |PRF| with the current [=credential=] for the lifetime of the credential.

    1. Use some unspecified mechanism to receive PRF inputs |salt1| and, optionally, |salt2| from the [=client=], in that order.
        If none are received, let |salt1| and |salt2| be undefined.

    1. If |salt1| is defined:
        1. Let |results| be an {{AuthenticationExtensionsPRFValues}} structure containing the evaluations of |PRF| at the given inputs:
            - Set <code>|results|.{{AuthenticationExtensionsPRFValues/first}}</code> to <code>PRF(|salt1|)</code>.
            - If |salt2| is defined,
                set <code>|results|.{{AuthenticationExtensionsPRFValues/second}}</code> to <code>PRF(|salt2|)</code>.
        1. Use some unspecified mechanism to convey |results| to the [=client=] as the PRF outputs.

: Client extension output
:: <xmp class="idl">
    dictionary AuthenticationExtensionsPRFOutputs {
        boolean enabled;
        AuthenticationExtensionsPRFValues results;
    };
    dictionary AuthenticationExtensionsPRFOutputsJSON {
        boolean enabled;
        AuthenticationExtensionsPRFValuesJSON results;
    };

    partial dictionary AuthenticationExtensionsClientOutputs {
        AuthenticationExtensionsPRFOutputs prf;
    };
    partial dictionary AuthenticationExtensionsClientOutputsJSON {
        AuthenticationExtensionsPRFOutputsJSON prf;
    };
    </xmp>

    <div dfn-type="dict-member" dfn-for="AuthenticationExtensionsPRFOutputs">
        :   <dfn>enabled</dfn>
        ::  [TRUE] if, and only if, the PRF is available for use with the created credential. This is only reported during [=registration=] and is not present in the case of [=authentication=].

        :   <dfn>results</dfn>
        ::  The results of evaluating the PRF for the inputs given in {{AuthenticationExtensionsPRFInputs/eval}} or {{AuthenticationExtensionsPRFInputs/evalByCredential}}. Outputs may not be available during [=registration=]; see comments in {{AuthenticationExtensionsPRFInputs/eval}}.

            Advisement:
            For some use cases, for example if PRF outputs are used to derive encryption keys to use only on the client side,
            it may be necessary to omit this {{AuthenticationExtensionsPRFOutputs/results}} output
            if the {{PublicKeyCredential}} is sent to a remote server,
            for example to perform the procedures in [[#sctn-rp-operations]].
            Note in particular that the {{RegistrationResponseJSON}} and {{AuthenticationResponseJSON}}
            returned by <code>{{PublicKeyCredential}}.{{PublicKeyCredential/toJSON()}}</code>
            will include this {{AuthenticationExtensionsPRFOutputs/results}} output if present.
    </div>


### Large blob storage extension (<dfn>largeBlob</dfn>) ### {#sctn-large-blob-extension}

This [=client extension|client=] [=registration extension=] and [=authentication extension=] allows a [=[RP]=] to store opaque data associated with a credential. Since [=authenticators=] can only store small amounts of data, and most [=[RPS]=] are online services that can store arbitrary amounts of state for a user, this is only useful in specific cases. For example, the [=[RP]=] might wish to issue certificates rather than run a centralised authentication service.

Note: [=[RPS]=] can assume that the opaque data will be compressed when being written to a space-limited device and so need not compress it themselves.

Since a certificate system needs to sign over the public key of the credential, and that public key is only available after creation, this extension does not add an ability to write blobs in the [=registration extension|registration=] context. However, [=[RPS]=] SHOULD use the [=registration extension=] when creating the credential if they wish to later use the [=authentication extension=].

Since certificates are sizable relative to the storage capabilities of typical authenticators, user agents SHOULD consider what indications and confirmations are suitable to best guide the user in allocating this limited resource and prevent abuse.

Note: In order to interoperate, user agents storing large blobs on authenticators using [[!FIDO-CTAP]] are expected to use the provisions detailed in that specification for storing [=large, per-credential blobs=].

Note: [=Roaming authenticators=] that use [[!FIDO-CTAP]] as their cross-platform transport protocol only support this [=largeblob|Large Blob=] extension for [=discoverable credentials=],
and might return an error unless
<code>{{PublicKeyCredentialCreationOptions/authenticatorSelection}}.{{AuthenticatorSelectionCriteria/residentKey}}</code>
is set to {{ResidentKeyRequirement/preferred}} or {{ResidentKeyRequirement/required}}.
However, [=authenticators=] that do not utilize [[!FIDO-CTAP]] do not necessarily restrict this extension to [=discoverable credentials=].

: Extension identifier
:: `largeBlob`

: Operation applicability
:: [=registration extension|Registration=] and [=authentication extension|authentication=]

: Client extension input
::  <xmp class="idl">
    partial dictionary AuthenticationExtensionsClientInputs {
        AuthenticationExtensionsLargeBlobInputs largeBlob;
    };
    partial dictionary AuthenticationExtensionsClientInputsJSON {
        AuthenticationExtensionsLargeBlobInputsJSON largeBlob;
    };

    enum LargeBlobSupport {
      "required",
      "preferred",
    };

    dictionary AuthenticationExtensionsLargeBlobInputs {
        DOMString support;
        boolean read;
        BufferSource write;
    };
    dictionary AuthenticationExtensionsLargeBlobInputsJSON {
        DOMString support;
        boolean read;
        Base64URLString write;
    };
    </xmp>

    <div dfn-type="dict-member" dfn-for="AuthenticationExtensionsLargeBlobInputs">
        :   <dfn>support</dfn>
        ::  A DOMString that takes one of the values of {{LargeBlobSupport}}. (See [[#sct-domstring-backwards-compatibility]].) Only valid during [=registration extension|registration=].

        :   <dfn>read</dfn>
        ::  A boolean that indicates that the [=[RP]=] would like to fetch the previously-written blob associated with the asserted credential. Only valid during [=authentication extension|authentication=].

        :   <dfn>write</dfn>
        ::  An opaque byte string that the [=[RP]=] wishes to store with the existing credential. Only valid during [=authentication extension|authentication=].
    </div>

: Client extension processing ([=registration extension|registration=])
::
       1. If {{AuthenticationExtensionsLargeBlobInputs/read}} or {{AuthenticationExtensionsLargeBlobInputs/write}} is present:
           1. Return a {{DOMException}} whose name is “{{NotSupportedError}}”.
       1. If {{AuthenticationExtensionsLargeBlobInputs/support}} is present and has the value {{LargeBlobSupport/required}}:
           1. Set {{AuthenticationExtensionsLargeBlobOutputs/supported}} to [TRUE].

               Note: This is in anticipation of an authenticator capable of storing large blobs becoming available.
               It occurs during extension processing in [step 12](#CreateCred-process-extensions) of {{PublicKeyCredential/[CREATE-METHOD]}}.
               The {{AuthenticationExtensionsLargeBlobOutputs}} will be abandoned if no satisfactory authenticator becomes available.

           1. If a [=create/candidate authenticator=] becomes available ([step 22](#CreateCred-async-loop) of {{PublicKeyCredential/[CREATE-METHOD]}}) then,
              before evaluating any <code>|options|</code>, [=iteration/continue=] (i.e. ignore the [=create/candidate authenticator=])
              if the [=create/candidate authenticator=] is not capable of storing large blobs.
       1. Otherwise (i.e. {{AuthenticationExtensionsLargeBlobInputs/support}} is absent or has the value {{LargeBlobSupport/preferred}}):
           1. If an [=create/selected authenticator|authenticator is selected=] and the [=create/selected authenticator=] supports large blobs, set {{AuthenticationExtensionsLargeBlobOutputs/supported}} to [TRUE], and [FALSE] otherwise.

: Client extension processing ([=authentication extension|authentication=])
::
       1. If {{AuthenticationExtensionsLargeBlobInputs/support}} is present:
           1. Return a {{DOMException}} whose name is “{{NotSupportedError}}”.
       1. If both {{AuthenticationExtensionsLargeBlobInputs/read}} and {{AuthenticationExtensionsLargeBlobInputs/write}} are present:
           1. Return a {{DOMException}} whose name is “{{NotSupportedError}}”.
       1. If {{AuthenticationExtensionsLargeBlobInputs/read}} is present and has the value [TRUE]:
           1. Initialize the [=client extension output=], {{AuthenticationExtensionsClientOutputs/largeBlob}}.
           1. If any authenticator indicates success (in {{PublicKeyCredential/[DISCOVER-METHOD]}}), attempt to read any largeBlob data associated with the asserted credential.
           1. If successful, set {{AuthenticationExtensionsLargeBlobOutputs/blob}} to the result.

              Note: If the read is not successful, {{AuthenticationExtensionsClientOutputs/largeBlob}} will be present in {{AuthenticationExtensionsClientOutputs}} but the {{AuthenticationExtensionsLargeBlobOutputs/blob}} member will not be present.

       1. If {{AuthenticationExtensionsLargeBlobInputs/write}} is present:
           1. If {{PublicKeyCredentialRequestOptions/allowCredentials}} does not contain exactly one element:
               1. Return a {{DOMException}} whose name is “{{NotSupportedError}}”.
           1. If the [[#sctn-getAssertion|assertion]] operation is successful, attempt to store the contents of {{AuthenticationExtensionsLargeBlobInputs/write}} on the [=authenticator=], associated with the indicated credential.
           1. Set {{AuthenticationExtensionsLargeBlobOutputs/written}} to `true` if successful and `false` otherwise.

: Client extension output
:: <xmp class="idl">
    partial dictionary AuthenticationExtensionsClientOutputs {
        AuthenticationExtensionsLargeBlobOutputs largeBlob;
    };
    partial dictionary AuthenticationExtensionsClientOutputsJSON {
        AuthenticationExtensionsLargeBlobOutputsJSON largeBlob;
    };

    dictionary AuthenticationExtensionsLargeBlobOutputs {
        boolean supported;
        ArrayBuffer blob;
        boolean written;
    };
    dictionary AuthenticationExtensionsLargeBlobOutputsJSON {
        boolean supported;
        Base64URLString blob;
        boolean written;
    };
    </xmp>

    <div dfn-type="dict-member" dfn-for="AuthenticationExtensionsLargeBlobOutputs">
        :   <dfn>supported</dfn>
        ::  [TRUE] if, and only if, the created credential supports storing large blobs. Only present in [=registration extension|registration=] outputs.

        :   <dfn>blob</dfn>
        ::  The opaque byte string that was associated with the credential identified by {{PublicKeyCredential/rawId}}. Only valid if {{AuthenticationExtensionsLargeBlobInputs/read}} was `true`.

        :   <dfn>written</dfn>
        ::  A boolean that indicates that the contents of {{AuthenticationExtensionsLargeBlobInputs/write}} were successfully stored on the [=authenticator=], associated with the specified credential.
    </div>


: Authenticator extension processing
:: [=largeblob|This extension=] directs the user-agent to cause the large blob to be stored on, or retrieved from, the authenticator. It thus does not specify any direct authenticator interaction for [=[RPS]=].


## Authenticator Extensions ## {#sctn-defined-authenticator-extensions}

This section defines extensions that are both [=client extensions=] and [=authenticator extensions=].

This section is currently empty.


# User Agent Automation # {#sctn-automation}

For the purposes of user agent automation and [=web application=] testing, this document defines a number of [[WebDriver]] [=extension commands=].

## WebAuthn WebDriver Extension Capability ## {#sctn-automation-webdriver-capability}

In order to advertise the availability of the [=extension commands=] defined below, a new [=extension capability=] is defined.

<figure id="table-virtualAuthenticatorsWebdriverCapability" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>Capability</th>
                <th>Key</th>
                <th>Value Type</th>
                <th>Description</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Virtual Authenticators Support</td>
                <td>`"webauthn:virtualAuthenticators"`</td>
                <td>boolean</td>
                <td>Indicates whether the [=endpoint node=] supports all [=Virtual Authenticators=] commands.</td>
            </tr>
        </tbody>
    </table>
</figure>

When [=validating capabilities=], the extension-specific substeps to validate `"webauthn:virtualAuthenticators"` with `value` are the following:

    1. If `value` is not a [=boolean=] return a [=WebDriver Error=] with [=WebDriver error code=] [=invalid argument=].
    2. Otherwise, let `deserialized` be set to `value`.

When [=matching capabilities=], the extension-specific steps to match `"webauthn:virtualAuthenticators"` with `value` are the following:

    1. If `value` is [TRUE] and the [=endpoint node=] does not support any of the [=Virtual Authenticators=] commands,
        the match is unsuccessful.
    2. Otherwise, the match is successful.

### <dfn>Authenticator Extension Capabilities</dfn> ### {#sctn-authenticator-extension-capabilities}

Additionally, [=extension capabilities=] are defined for every [=authenticator extension=]
(i.e. those defining [=authenticator extension processing=]) defined in this specification:

<figure id="table-virtualAuthenticatorsExtensionsWebdriverCapability" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>Capability</th>
                <th>Key</th>
                <th>Value Type</th>
                <th>Description</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Pseudo-Random Function Extension Support</td>
                <td>`"webauthn:extension:prf"`</td>
                <td>boolean</td>
                <td>Indicates whether the [=endpoint node=] WebAuthn WebDriver implementation supports the [=prf=] extension.</td>
            </tr>
            <tr>
                <td>Large Blob Storage Extension Support</td>
                <td>`"webauthn:extension:largeBlob"`</td>
                <td>boolean</td>
                <td>Indicates whether the [=endpoint node=] WebAuthn WebDriver implementation supports the [=largeBlob=] extension.</td>
            </tr>
            <tr>
                <td>credBlob Extension Support</td>
                <td>`"webauthn:extension:credBlob"`</td>
                <td>boolean</td>
                <td>Indicates whether the [=endpoint node=] WebAuthn WebDriver implementation supports the `credBlob` extension defined in [[FIDO-CTAP]].</td>
            </tr>
        </tbody>
    </table>
</figure>

When [=validating capabilities=], the extension-specific substeps to validate an [=authenticator extension capability=] `key` with `value` are the following:

    1. If `value` is not a [=boolean=] return a [=WebDriver Error=] with [=WebDriver error code=] [=invalid argument=].
    2. Otherwise, let `deserialized` be set to `value`.

When [=matching capabilities=], the extension-specific steps to match an [=authenticator extension capability=] `key` with `value` are the following:

    1. If `value` is [TRUE] and the [=endpoint node=] WebAuthn WebDriver implementation does not support the [=authenticator extension=] identified by the `key`,
        the match is unsuccessful.
    2. Otherwise, the match is successful.

User-Agents implementing defined [=authenticator extensions=] SHOULD implement the corresponding [=authenticator extension capability=].

## <dfn>Virtual Authenticators</dfn> ## {#sctn-automation-virtual-authenticators}

These WebDriver [=extension commands=] create and interact with [=Virtual Authenticators=]: software implementations of the
<a>Authenticator Model</a>. <a>Virtual Authenticators</a> are stored in a <dfn>Virtual Authenticator Database</dfn>.
Each stored [=virtual authenticator=] has the following properties:

: <dfn>authenticatorId</dfn>
:: An non-null string made using up to 48 characters from the `unreserved` production defined in Appendix A of [[RFC3986]]
    that uniquely identifies the [=Virtual Authenticator=].
: |protocol|
:: The protocol the [=Virtual Authenticator=] speaks: one of `"ctap1/u2f"`, `"ctap2"` or `"ctap2_1"` [[FIDO-CTAP]].
: |transport|
:: The {{AuthenticatorTransport}} simulated. If the |transport| is set to {{AuthenticatorTransport/internal}}, the
    authenticator simulates [=platform attachment=]. Otherwise, it simulates [=cross-platform attachment=].
: |hasResidentKey|
:: If set to [TRUE] the authenticator will support [=client-side discoverable credentials=].
: |hasUserVerification|
:: If set to [TRUE], the authenticator supports [=user verification=].
: |isUserConsenting|
:: Determines the result of all [=user consent=] [=authorization gestures=], and by extension, any [=test of user presence=]
    performed on the [=Virtual Authenticator=]. If set to [TRUE], a [=user consent=] will always be granted. If set to
    [FALSE], it will not be granted.
: |isUserVerified|
:: Determines the result of [=User Verification=] performed on the [=Virtual Authenticator=]. If set to [TRUE],
    [=User Verification=] will always succeed. If set to [FALSE], it will fail.

    Note: This property has no effect if |hasUserVerification| is set to [FALSE].
: |extensions|
:: A string array containing the [=extension identifiers=] supported by the [=Virtual Authenticator=].

    A [=Virtual authenticator=] MUST support all [=authenticator extensions=] present in its |extensions| array.
    It MUST NOT support any [=authenticator extension=] not present in its |extensions| array.

: |defaultBackupEligibility|
:: Determines the default state of the [=backup eligibility=] [=credential property=] for any newly created [=Public Key Credential Source=].
    This value MUST be reflected by the [=BE=] [=authenticator data=] [=flag=] when performing an [=authenticatorMakeCredential=]
    operation with this [=virtual authenticator=].
: |defaultBackupState|
:: Determines the default state of the [=backup state=] [=credential property=] for any newly created [=Public Key Credential Source=].
    This value MUST be reflected by the [=BS=] [=authenticator data=] [=flag=] when performing an [=authenticatorMakeCredential=]
    operation with this [=virtual authenticator=].

## <dfn>Add Virtual Authenticator</dfn> ## {#sctn-automation-add-virtual-authenticator}

The [=Add Virtual Authenticator=] WebDriver [=extension command=] creates a software [=Virtual Authenticator=]. It is
defined as follows:

<figure id="table-addVirtualAuthenticator" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>HTTP Method</th>
                <th>URI Template</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>POST</td>
                <td>`/session/{session id}/webauthn/authenticator`</td>
            </tr>
        </tbody>
    </table>
</figure>

The <dfn>Authenticator Configuration</dfn> is a JSON [=Object=] passed to the [=remote end steps=] as |parameters|. It contains the following |key| and |value| pairs:

<figure id="table-authenticatorConfiguration" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>Key</th>
                <th>Value Type</th>
                <th>Valid Values</th>
                <th>Default</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>|protocol|</td>
                <td>string</td>
                <td>`"ctap1/u2f"`, `"ctap2"`, `"ctap2_1"`</td>
                <td>None</td>
            </tr>
            <tr>
                <td>|transport|</td>
                <td>string</td>
                <td>{{AuthenticatorTransport}} values</td>
                <td>None</td>
            </tr>
            <tr>
                <td>|hasResidentKey|</td>
                <td>boolean</td>
                <td>[TRUE], [FALSE]</td>
                <td>[FALSE]</td>
            </tr>
            <tr>
                <td>|hasUserVerification|</td>
                <td>boolean</td>
                <td>[TRUE], [FALSE]</td>
                <td>[FALSE]</td>
            </tr>
            <tr>
                <td>|isUserConsenting|</td>
                <td>boolean</td>
                <td>[TRUE], [FALSE]</td>
                <td>[TRUE]</td>
            </tr>
            <tr>
                <td>|isUserVerified|</td>
                <td>boolean</td>
                <td>[TRUE], [FALSE]</td>
                <td>[FALSE]</td>
            </tr>
            <tr>
                <td>|extensions|</td>
                <td>string array</td>
                <td>An array containing [=extension identifiers=]</td>
                <td>Empty array</td>
            </tr>
            <tr>
                <td>|defaultBackupEligibility|</td>
                <td>boolean</td>
                <td>[TRUE], [FALSE]</td>
                <td>[FALSE]</td>
            </tr>
            <tr>
                <td>|defaultBackupState|</td>
                <td>boolean</td>
                <td>[TRUE], [FALSE]</td>
                <td>[FALSE]</td>
            </tr>
        </tbody>
    </table>
</figure>

The [=remote end steps=] are:

 1. If |parameters| is not a JSON [=Object=], return a [=WebDriver error=] with [=WebDriver error code=]
     [=invalid argument=].

     Note: |parameters| is an [=Authenticator Configuration=] object.
 1. Let |authenticator| be a new [=Virtual Authenticator=].
 1. For each enumerable [=own property=] in |parameters|:
    1. Let |key| be the name of the property.
    1. Let |value| be the result of [=getting a property=] named |key| from |parameters|.
    1. If there is no matching `key` for |key| in [=Authenticator Configuration=], return a [=WebDriver error=] with
        [=WebDriver error code=] [=invalid argument=].
    1. If |value| is not one of the `valid values` for that |key|, return a [=WebDriver error=] with [=WebDriver error code=]
        [=invalid argument=].
    1. [=Set a property=] |key| to |value| on |authenticator|.
 1. For each property in [=Authenticator Configuration=] with a default defined:
    1. If `key` is not a defined property of |authenticator|, [=set a property=] `key` to `default` on |authenticator|.
 1. For each property in [=Authenticator Configuration=]:
    1. If `key` is not a defined property of |authenticator|, return a [=WebDriver error=] with [=WebDriver error code=]
        [=invalid argument=].
 1. For each |extension| in |authenticator|.|extensions|:
    1. If |extension| is not an [=extension identifier=] supported by the [=endpoint node=] WebAuthn WebDriver implementation,
        return a [=WebDriver error=] with [=WebDriver error code=] [=unsupported operation=].
 1. Generate a valid unique [=authenticatorId=].
 1. [=Set a property=] `authenticatorId` to |authenticatorId| on |authenticator|.
 1. Store |authenticator| in the [=Virtual Authenticator Database=].
 1. Return [=success=] with data |authenticatorId|.

## <dfn>Remove Virtual Authenticator</dfn> ## {#sctn-automation-remove-virtual-authenticator}

The [=Remove Virtual Authenticator=] WebDriver [=extension command=] removes a previously created [=Virtual Authenticator=].
It is defined as follows:

<figure id="table-removeVirtualAuthenticator" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>HTTP Method</th>
                <th>URI Template</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>DELETE</td>
                <td>`/session/{session id}/webauthn/authenticator/{authenticatorId}`</td>
            </tr>
        </tbody>
    </table>
</figure>

The [=remote end steps=] are:

 1. If |authenticatorId| does not match any [=Virtual Authenticator=] stored in the [=Virtual Authenticator
     Database=], return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Remove the [=Virtual Authenticator=] identified by |authenticatorId| from the [=Virtual Authenticator Database=]
 1. Return [=success=].

## <dfn>Add Credential</dfn> ## {#sctn-automation-add-credential}

The [=Add Credential=] WebDriver [=extension command=] injects a [=Public Key Credential Source=] into an existing
[=Virtual Authenticator=]. It is defined as follows:

<figure id="table-addCredential" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>HTTP Method</th>
                <th>URI Template</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>POST</td>
                <td>`/session/{session id}/webauthn/authenticator/{authenticatorId}/credential`</td>
            </tr>
        </tbody>
    </table>
</figure>

The <dfn>Credential Parameters</dfn> is a JSON [=Object=] passed to the [=remote end steps=] as |parameters|. It contains the following |key| and |value| pairs:

<figure id="table-credentialParameters" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>Key</th>
                <th>Description</th>
                <th>Value Type</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>|credentialId|</td>
                <td>The [=public key credential source/id|Credential ID=] encoded using [=Base64url Encoding=].</td>
                <td>string</td>
            </tr>
            <tr>
                <td>|isResidentCredential|</td>
                <td>
                    If set to [TRUE], a [=client-side discoverable credential=] is created. If set to [FALSE], a [=server-side credential=]
                    is created instead.
                </td>
                <td>boolean</td>
            </tr>
            <tr>
                <td>|rpId|</td>
                <td>The [=public key credential source/rpId|Relying Party ID=] the credential is scoped to.</td>
                <td>string</td>
            </tr>
            <tr>
                <td>|privateKey|</td>
                <td>
                    An asymmetric key package containing a single [=public key credential source/privateKey|private key=]
                    per [[RFC5958]], encoded using [=Base64url Encoding=].
                </td>
                <td>string</td>
            </tr>
            <tr>
                <td>|userHandle|</td>
                <td>
                    The [=public key credential source/userHandle=] associated to the credential encoded using
                    [=Base64url Encoding=]. This property may not be defined.
                </td>
                <td>string</td>
            </tr>
            <tr>
                <td>|signCount|</td>
                <td>The initial value for a [=signature counter=] associated to the [=public key credential source=].</td>
                <td>number</td>
            </tr>
            <tr>
                <td>|largeBlob|</td>
                <td>
                    The [=large, per-credential blob=] associated to the [=public key credential source=], encoded using [=Base64url Encoding=].
                    This property may not be defined.
                </td>
                <td>string</td>
            </tr>
            <tr>
                <td>|backupEligibility|</td>
                <td>
                    The simulated [=backup eligibility=] for the [=public key credential source=]. If unset, the value will default to the
                    [=virtual authenticator=]'s |defaultBackupEligibility| property.
                    The simulated [=backup eligibility=] MUST be reflected by the [=BE=] [=authenticator data=] [=flag=] when performing
                    an [=authenticatorGetAssertion=] operation with this [=public key credential source=].
                </td>
                <td>boolean</td>
            </tr>
            <tr>
                <td>|backupState|</td>
                <td>
                    The simulated [=backup state=] for the [=public key credential source=]. If unset, the value will default to the
                    [=virtual authenticator=]'s |defaultBackupState| property.
                    The simulated [=backup state=] MUST be reflected by the [=BS=] [=authenticator data=] [=flag=] when performing
                    an [=authenticatorGetAssertion=] operation with this [=public key credential source=].
                </td>
                <td>boolean</td>
            </tr>
            <tr>
                <td>|userName|</td>
                <td>
                    The {{PublicKeyCredentialUserEntity|user}}'s {{PublicKeyCredentialEntity/name}} associated to the credential.
                    If unset, the value will default to the empty string.
                </td>
                <td>string</td>
            </tr>
            <tr>
                <td>|userDisplayName|</td>
                <td>
                    The {{PublicKeyCredentialUserEntity|user}}'s {{PublicKeyCredentialUserEntity/displayName}} associated to the credential.
                    If unset, the value will default to the empty string.
                </td>
                <td>string</td>
            </tr>
        </tbody>
    </table>
</figure>

The [=remote end steps=] are:

 1. If |parameters| is not a JSON [=Object=], return a [=WebDriver error=] with [=WebDriver error code=]
     [=invalid argument=].

     Note: |parameters| is a [=Credential Parameters=] object.
 1. Let |credentialId| be the result of decoding [=Base64url Encoding=] on the |parameters|' |credentialId| property.
 1. If |credentialId| is failure, return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Let |isResidentCredential| be the |parameters|' |isResidentCredential| property.
 1. If |isResidentCredential| is not defined, return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Let |rpId| be the |parameters|' |rpId| property.
 1. If |rpId| is not a valid [=RP ID=], return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Let |privateKey| be the result of decoding [=Base64url Encoding=] on the |parameters|' |privateKey| property.
 1. If |privateKey| is failure, return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. If |privateKey| is not a validly-encoded asymmetric key package containing a single ECDSA private key on the P-256
     curve per [[RFC5958]], return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. If the |parameters|' |userHandle| property is defined:
     1. Let |userHandle| be the result of decoding [=Base64url Encoding=] on the |parameters|' |userHandle| property.
     1. If |userHandle| is failure, return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Otherwise:
    1. If |isResidentCredential| is [TRUE], return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
    1. Let |userHandle| be `null`.
 1. If |authenticatorId| does not match any [=Virtual Authenticator=] stored in the [=Virtual Authenticator
     Database=], return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Let |authenticator| be the [=Virtual Authenticator=] matched by |authenticatorId|.
 1. If |isResidentCredential| is [TRUE] and the |authenticator|'s |hasResidentKey| property is [FALSE], return a
     [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. If the |authenticator| supports the [=largeBlob=] extension and the |parameters|' |largeBlob| feature is defined:
     1. Let |largeBlob| be the result of decoding [=Base64url Encoding=] on the |parameters|' |largeBlob| property.
     1. If |largeBlob| is failure, return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Otherwise:
     1. Let |largeBlob| be `null`.
 1. Let |backupEligibility| be the |parameters|' |backupEligibility| property.
 1. If |backupEligibility| is not defined, set |backupEligibility| to the value of the |authenticator|'s |defaultBackupEligibility|.
 1. Let |backupState| be the |parameters|' |backupState| property.
 1. If |backupState| is not defined, set |backupState| to the value of the |authenticator|'s |defaultBackupState|.
 1. Let |userName| be the |parameters|' |userName| property.
 1. If |userName| is not defined, set |userName| to the empty string.
 1. Let |userDisplayName| be the |parameters|' |userDisplayName| property.
 1. If |userDisplayName| is not defined, set |userDisplayName| to the empty string.
 1. Let |credential| be a new [=Client-side discoverable Public Key Credential Source=] if |isResidentCredential| is [TRUE]
     or a [=Server-side Public Key Credential Source=] otherwise whose items are:
    : [=public key credential source/type=]
    :: {{public-key}}
    : [=public key credential source/id=]
    :: |credentialId|
    : [=public key credential source/privateKey=]
    :: |privateKey|
    : [=public key credential source/rpId=]
    :: |rpId|
    : [=public key credential source/userHandle=]
    :: |userHandle|
    : [=public key credential source/otherUI=]
    :: Construct from |userName| and |userDisplayName|.
 1. Set the |credential|'s [=backup eligibility=] [=credential property=] to |backupEligibility|.
 1. Set the |credential|'s [=backup state=] [=credential property=] to |backupState|.
 1. Associate a [=signature counter=] |counter| to the |credential| with a starting value equal to the |parameters|'
     |signCount| or `0` if |signCount| is `null`.
 1. If |largeBlob| is not `null`, set the [=large, per-credential blob=] associated to the |credential| to |largeBlob|.
 1. Store the |credential| and |counter| in the database of the |authenticator|.
 1. Return [=success=].

## <dfn>Get Credentials</dfn> ## {#sctn-automation-get-credentials}

The [=Get Credentials=] WebDriver [=extension command=] returns one [=Credential Parameters=] object for every
[=Public Key Credential Source=] stored in a [=Virtual Authenticator=], regardless of whether they were
stored using [=Add Credential=] or {{CredentialsContainer/create()|navigator.credentials.create()}}. It is defined as follows:

<figure id="table-getCredentials" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>HTTP Method</th>
                <th>URI Template</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>GET</td>
                <td>`/session/{session id}/webauthn/authenticator/{authenticatorId}/credentials`</td>
            </tr>
        </tbody>
    </table>
</figure>

The [=remote end steps=] are:

 1. If |authenticatorId| does not match any [=Virtual Authenticator=] stored in the [=Virtual Authenticator
     Database=], return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Let |credentialsArray| be an empty array.
 1. For each [=Public Key Credential Source=] |credential|, managed by the authenticator identified by |authenticatorId|,
    construct a corresponding [=Credential Parameters=] [=Object=] and add it to |credentialsArray|.
 1. Return [=success=] with data containing |credentialsArray|.

## <dfn>Remove Credential</dfn> ## {#sctn-automation-remove-credential}

The [=Remove Credential=] WebDriver [=extension command=] removes a [=Public Key Credential Source=] stored on a
[=Virtual Authenticator=]. It is defined as follows:

<figure id="table-removeCredential" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>HTTP Method</th>
                <th>URI Template</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>DELETE</td>
                <td>`/session/{session id}/webauthn/authenticator/{authenticatorId}/credentials/{credentialId}`</td>
            </tr>
        </tbody>
    </table>
</figure>

The [=remote end steps=] are:

 1. If |authenticatorId| does not match any [=Virtual Authenticator=] stored in the [=Virtual Authenticator
     Database=], return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Let |authenticator| be the [=Virtual Authenticator=] identified by |authenticatorId|.
 1. If |credentialId| does not match any [=Public Key Credential Source=] managed by |authenticator|, return a [=WebDriver error=]
     with [=WebDriver error code=] [=invalid argument=].
 1. Remove the [=Public Key Credential Source=] identified by |credentialId| managed by |authenticator|.
 1. Return [=success=].

## <dfn>Remove All Credentials</dfn> ## {#sctn-automation-remove-all-credentials}

The [=Remove All Credentials=] WebDriver [=extension command=] removes all [=Public Key Credential Sources=] stored on a
[=Virtual Authenticator=]. It is defined as follows:

<figure id="table-removeAllCredentials" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>HTTP Method</th>
                <th>URI Template</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>DELETE</td>
                <td>`/session/{session id}/webauthn/authenticator/{authenticatorId}/credentials`</td>
            </tr>
        </tbody>
    </table>
</figure>

The [=remote end steps=] are:

 1. If |authenticatorId| does not match any [=Virtual Authenticator=] stored in the [=Virtual Authenticator
     Database=], return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Remove all [=Public Key Credential Sources=] managed by the [=Virtual Authenticator=] identified by |authenticatorId|.
 1. Return [=success=].

## <dfn>Set User Verified</dfn> ## {#sctn-automation-set-user-verified}

The [=Set User Verified=] [=extension command=] sets the |isUserVerified| property on the [=Virtual Authenticator=]. It
is defined as follows:

<figure id="table-setUserVerified" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>HTTP Method</th>
                <th>URI Template</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>POST</td>
                <td>`/session/{session id}/webauthn/authenticator/{authenticatorId}/uv`</td>
            </tr>
        </tbody>
    </table>
</figure>

The [=remote end steps=] are:

 1. If |parameters| is not a JSON [=Object=], return a [=WebDriver error=] with [=WebDriver error code=]
     [=invalid argument=].
 1. If |authenticatorId| does not match any [=Virtual Authenticator=] stored in the [=Virtual Authenticator
     Database=], return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. If |isUserVerified| is not a defined property of |parameters|, return a [=WebDriver error=] with [=WebDriver error code=]
     [=invalid argument=].
 1. Let |authenticator| be the [=Virtual Authenticator=] identified by |authenticatorId|.
 1. Set the |authenticator|'s |isUserVerified| property to the |parameters|' |isUserVerified| property.
 1. Return [=success=].

## <dfn>Set Credential Properties</dfn> ## {#sctn-automation-set-credential-properties}

The [=Set Credential Properties=] [=extension command=] allows setting the |backupEligibility| and |backupState| [=credential properties=] of
a [=Virtual Authenticator=]'s [=public key credential source=]. It is defined as follows:

<figure id="table-setFlags" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>HTTP Method</th>
                <th>URI Template</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>POST</td>
                <td>`/session/{session id}/webauthn/authenticator/{authenticatorId}/credentials/{credentialId}/props`</td>
            </tr>
        </tbody>
    </table>
</figure>

The <dfn>Set Credential Properties Parameters</dfn> is a JSON [=Object=] passed to the [=remote end steps=] as |parameters|.
It contains the following |key| and |value| pairs:

<figure id="table-setCredentialPropertiesParameters" class="table">
    <table class="data">
        <thead>
            <tr>
                <th>Key</th>
                <th>Description</th>
                <th>Value Type</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>|backupEligibility|</td>
                <td>The [=backup eligibility=] [=credential property=].</td>
                <td>boolean</td>
            </tr>
            <tr>
                <td>|backupState|</td>
                <td>The [=backup state=] [=credential property=].</td>
                <td>boolean</td>
            </tr>
        </tbody>
    </table>
</figure>

The [=remote end steps=] are:

 1. If |parameters| is not a JSON [=Object=], return a [=WebDriver error=] with [=WebDriver error code=]
     [=invalid argument=].

     Note: |parameters| is a [=Set Credential Properties Parameters=] object.
 1. If |authenticatorId| does not match any [=Virtual Authenticator=] stored in the [=Virtual Authenticator
     Database=], return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Let |credential| be the [=public key credential source=] managed by |authenticator| matched by |credentialId|.
 1. If |credential| is empty, return a [=WebDriver error=] with [=WebDriver error code=] [=invalid argument=].
 1. Let |backupEligibility| be the |parameters|' |backupEligibility| property.
 1. If |backupEligibility| is defined, set the [=backup eligibility=] [=credential property=] of |credential| to the value of |backupEligibility|.

    Note: Normally, the |backupEligibility| property is permanent to a [=public key credential source=].
    [=Set Credential Properties=] allows changing it for testing and debugging purposes.

 1. Let |backupState| be the |parameters|' |backupState| property.
 1. If |backupState| is defined, set the [=backup state=] [=credential property=] of |credential| to the value of |backupState|.
 1. Return [=success=].

# IANA Considerations # {#sctn-IANA}

## WebAuthn Attestation Statement Format Identifier Registrations Updates ## {#sctn-att-fmt-reg-update}

This section updates the below-listed attestation statement formats defined in Section [[#sctn-defined-attestation-formats]] in the
IANA "WebAuthn Attestation Statement Format Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]], originally registered in [[WebAuthn-1]], to point to this specification.

- WebAuthn Attestation Statement Format Identifier: packed
- Description: The "packed" attestation statement format is a WebAuthn-optimized format for [=attestation=]. It uses a very
    compact but still extensible encoding method. This format is implementable by authenticators with limited resources (e.g.,
    secure elements).
- Specification Document: Section [[#sctn-packed-attestation]] of this specification
    <br/><br/>
- WebAuthn Attestation Statement Format Identifier: tpm
- Description: The TPM attestation statement format returns an attestation statement in the same format as the packed
    attestation statement format, although the rawData and signature fields are computed differently.
- Specification Document: Section [[#sctn-tpm-attestation]] of this specification
    <br/><br/>
- WebAuthn Attestation Statement Format Identifier: android-key
- Description: [=Platform authenticators=] on versions "N", and later, may provide this proprietary "hardware
    attestation" statement.
- Specification Document: Section [[#sctn-android-key-attestation]] of this specification
    <br/><br/>
- WebAuthn Attestation Statement Format Identifier: android-safetynet
- Description: Android-based [=platform authenticators=] MAY produce an attestation statement based on the Android
    SafetyNet API.
- Specification Document: Section [[#sctn-android-safetynet-attestation]] of this specification
    <br/><br/>
- WebAuthn Attestation Statement Format Identifier: fido-u2f
- Description: Used with FIDO U2F authenticators
- Specification Document: Section [[#sctn-fido-u2f-attestation]] of this specification


## WebAuthn Attestation Statement Format Identifier Registrations ## {#sctn-att-fmt-reg}

This section registers the below-listed attestation statement formats, newly defined in Section [[#sctn-defined-attestation-formats]], in the IANA "WebAuthn Attestation Statement Format Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]].

- WebAuthn Attestation Statement Format Identifier: apple
- Description: Used with Apple devices' [=platform authenticators=]
- Specification Document: Section [[#sctn-apple-anonymous-attestation]] of this specification
    <br/><br/>
- WebAuthn Attestation Statement Format Identifier: none
- Description: Used to replace any authenticator-provided attestation statement when a [=[WRP]=] indicates it does not wish to receive attestation information.
- Specification Document: Section [[#sctn-none-attestation]] of this specification




## WebAuthn Extension Identifier Registrations Updates ## {#sctn-extensions-reg-update}

This section updates the below-listed [=extension identifier=] values defined in Section [[#sctn-defined-extensions]] in the IANA "WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]], originally registered in [[WebAuthn-1]], to point to this specification.

- WebAuthn Extension Identifier: appid
- Description: This [=authentication extension=] allows [=[WRPS]=] that have previously registered a credential using the legacy
    FIDO JavaScript APIs to request an assertion.
- Specification Document: Section [[#sctn-appid-extension]] of this specification
    <br/><br/>


## WebAuthn Extension Identifier Registrations ## {#sctn-extensions-reg}

This section registers the below-listed [=extension identifier=] values, newly defined in Section [[#sctn-defined-extensions]], in the IANA "WebAuthn Extension Identifiers" registry [[!IANA-WebAuthn-Registries]] established by [[!RFC8809]].

- WebAuthn Extension Identifier: appidExclude
- Description: This registration extension allows [=[WRPS]=] to exclude authenticators that contain specified credentials that were created with the legacy FIDO U2F JavaScript API [[FIDOU2FJavaScriptAPI]].
- Specification Document: Section [[#sctn-appid-exclude-extension]] of this specification
    <br/><br/>
- WebAuthn Extension Identifier: credProps
- Description: This [=client extension|client=] [=registration extension=] enables reporting of a newly-created [=credential=]'s properties,
    as determined by the [=client=], to the calling [=[WRP]=]'s [=web application=].
- Specification Document: Section [[#sctn-authenticator-credential-properties-extension]] of this specification
    <br/><br/>
- WebAuthn Extension Identifier: largeBlob
- Description: This [=client extension|client=] [=registration extension=] and [=authentication extension=] allows a [=[RP]=] to store opaque data associated with a credential.
- Specification Document: Section [[#sctn-large-blob-extension]] of this specification


# Security Considerations # {#sctn-security-considerations}

This specification defines a [[#sctn-api|Web API]] and a cryptographic peer-entity authentication protocol.
The [=Web Authentication API=] allows Web developers (i.e., "authors") to utilize the Web Authentication protocol in their
[=registration=] and [=authentication=] [=ceremonies=].
The entities comprising the Web Authentication protocol endpoints are user-controlled [=[WAA]s=] and a [=[WRP]=]'s
computing environment hosting the [=[RP]=]'s [=web application=].
In this model, the user agent, together with the [=[WAC]=], comprise an intermediary between [=authenticators=] and [=[RPS]=].
Additionally, [=authenticators=] can [=attestation|attest=] to [=[RPS]=] as to their provenance.

At this time, this specification does not feature detailed security considerations. However, the [[FIDOSecRef]] document provides a security analysis which is overall applicable to this specification.
Also, the [[FIDOAuthnrSecReqs]] document suite provides useful information about [=authenticator=] security characteristics.

The below subsections comprise the current Web Authentication-specific security considerations.
They are divided by audience;
general security considerations are direct subsections of this section,
while security considerations specifically for [=authenticator=], [=client=] and [=[RP]=] implementers
are grouped into respective subsections.


## Credential ID Unsigned ## {#sctn-credentialIdSecurity}

The [=credential ID=] accompanying an [=authentication assertion=] is not signed.
This is not a problem because all that would happen if an [=authenticator=] returns
the wrong [=credential ID=], or if an attacker intercepts and manipulates the [=credential ID=], is that the [=[WRP]=] would not look up the correct
[=credential public key=] with which to verify the returned signed [=authenticator data=]
(a.k.a., [=assertion=]), and thus the interaction would end in an error.


## Physical Proximity between Client and Authenticator ## {#sctn-client-authenticator-proximity}

In the WebAuthn [=authenticator model=], it is generally assumed that [=roaming authenticators=]
are physically close to, and communicate directly with, the [=client=].
This arrangement has some important advantages.

The promise of physical proximity between [=client=] and [=authenticator=]
is a key strength of a [=something you have=] [=authentication factor=].
For example, if a [=roaming authenticator=] can communicate only via USB or Bluetooth,
the limited range of these transports ensures that any malicious actor
must physically be within that range in order to interact with the [=authenticator=].
This is not necessarily true of an [=authenticator=] that can be invoked remotely &mdash;
even if the [=authenticator=] verifies [=user present|user presence=],
users can be tricked into authorizing remotely initiated malicious requests.

Direct communication between [=client=] and [=authenticator=]
means the [=client=] can enforce the [=scope=] restrictions for [=credentials=].
By contrast, if the communication between [=client=] and [=authenticator=] is mediated by some third party,
then the [=client=] has to trust the third party to
enforce the [=scope=] restrictions and control access to the [=authenticator=].
Failure to do either could result in
a malicious [=[RP]=] receiving [=authentication assertions=] valid for other [=[RPS]=],
or in a malicious user gaining access to [=authentication assertions=] for other users.

If designing a solution where the [=authenticator=] does not need to be physically close to the [=client=],
or where [=client=] and [=authenticator=] do not communicate directly,
designers SHOULD consider how this affects the enforcement of [=scope=] restrictions
and the strength of the [=authenticator=] as a [=something you have=] authentication factor.


## Security considerations for [=authenticators=] <span id="sctn-attestation-security-considerations"></span> ## {#sctn-security-considerations-authenticator}
<!-- Note: the above <span> is there to preserve the #sctn-attestation-security-considerations anchor although the section it was
tied to has been removed. The section had no text of its own and served only to group the following two subsections together. -->

### Attestation Certificate Hierarchy ### {#sctn-cert-hierarchy}

A 3-tier hierarchy for attestation certificates is RECOMMENDED (i.e., Attestation Root, Attestation Issuing CA, Attestation
Certificate). It is also RECOMMENDED that for each [=[WAA]=] device line (i.e., model), a separate issuing CA is
used to help facilitate isolating problems with a specific version of an authenticator model.

If the attestation root certificate is not dedicated to a single [=[WAA]=] device line (i.e., AAGUID), the AAGUID
SHOULD be specified in the attestation certificate itself, so that it can be verified against the [=authenticator data=].


### Attestation Certificate and Attestation Certificate CA Compromise ### {#sctn-ca-compromise}

When an intermediate CA or a root CA used for issuing attestation certificates is compromised, [=[WAA]=]
[=attestation key pairs=] are still safe although their certificates can no longer be trusted. A [=[WAA]=] manufacturer that
has recorded the [=attestation public keys=] for their [=authenticator=] models can issue new [=attestation certificates=] for these keys from a new
intermediate CA or from a new root CA. If the root CA changes, the [=[WRPS]=]  MUST update their trusted root certificates
accordingly.

A [=[WAA]=] [=attestation certificate=] MUST be revoked by the issuing CA if its [=attestation private key|private key=] has been compromised. A WebAuthn
Authenticator manufacturer may need to ship a firmware update and inject new [=attestation private keys=]
and [=attestation certificate|certificates=] into already
manufactured [=[WAA]s=], if the exposure was due to a firmware flaw. (The process by which this happens is out of
scope for this specification.) If the [=[WAA]=] manufacturer does not have this capability, then it may not be
possible for [=[RPS]=] to trust any further [=attestation statements=] from the affected [=[WAA]s=].

See also the related security consideration for [=[RPS]=] in [[#sctn-revoked-attestation-certificates]].

<!-- no sec cons for clients enumerated at this time
## Security considerations for [=clients=] ## {#sctn-security-considerations-client}
-->

## Security considerations for [=[RPS]=] ## {#sctn-security-considerations-rp}

### Security Benefits for [WRPS] ### {#sctn-rp-benefits}

The main benefits offered to [=[WRPS]=] by this specification include:

1. Users and accounts can be secured using widely compatible, easy-to-use multi-factor authentication.
1. The [=[RP]=] does not need to provision [=authenticator=] hardware to its users. Instead, each user can independently obtain
    any conforming [=authenticator=] and use that same [=authenticator=] with any number of [=[RPS]=]. The [=[RP]=] can optionally
    enforce requirements on [=authenticators=]' security properties by inspecting the [=attestation statements=] returned from the
    [=authenticators=].
1. [=Authentication ceremonies=] are resistant to [=man-in-the-middle attacks=].
    Regarding [=registration ceremonies=], see [[#sctn-attestation-limitations]], below.
1. The [=[RP]=] can automatically support multiple types of [=user verification=] - for example PIN, biometrics and/or future
    methods - with little or no code change, and can let each user decide which they prefer to use via their choice of
    [=authenticator=].
1. The [=[RP]=] does not need to store additional secrets in order to gain the above benefits.

As stated in the [[#sctn-conforming-relying-parties|Conformance]] section, the [=[RP]=] MUST behave as described in [[#sctn-rp-operations]]
to obtain all of the above security benefits. However, one notable use case that departs slightly from this is described below in [[#sctn-attestation-limitations]].


### Visibility Considerations for Embedded Usage ### {#sctn-seccons-visibility}

Simplistic use of WebAuthn in an embedded context, e.g., within <{iframe}>s as described in [[#sctn-iframe-guidance]], may make users vulnerable to <dfn>UI Redressing</dfn> attacks, also known as "[Clickjacking](https://en.wikipedia.org/wiki/Clickjacking)". This is where an attacker overlays their own UI on top of a [=[RP]=]'s intended UI and attempts to trick the user into performing unintended actions with the [=[RP]=]. For example, using these techniques, an attacker might be able to trick users into purchasing items, transferring money, etc.

Even though WebAuthn-specific UI is typically handled by the [=client platform=] and thus is not vulnerable to [=UI Redressing=], it is likely important for an [=[RP]=] having embedded WebAuthn-wielding content to ensure that their content's UI is visible to the user. An emerging means to do so is by observing the status of the experimental [Intersection Observer v2](https://w3c.github.io/IntersectionObserver/v2/)'s `isVisible` attribute. For example, the [=[RP]=]'s script running in the embedded context could pre-emptively load itself in a popup window if it detects `isVisble` being set to `false`, thus side-stepping any occlusion of their content.



### Cryptographic Challenges ### {#sctn-cryptographic-challenges}

As a cryptographic protocol, Web Authentication is dependent upon randomized challenges
to avoid replay attacks. Therefore, the values of both {{PublicKeyCredentialCreationOptions}}.{{PublicKeyCredentialCreationOptions/challenge}} and {{PublicKeyCredentialRequestOptions}}.{{PublicKeyCredentialRequestOptions/challenge}} MUST be randomly generated
by [=[RPS]=] in an environment they trust (e.g., on the server-side), and the
returned {{CollectedClientData/challenge}} value in the client's
response MUST match what was generated. This SHOULD be done in a fashion that does not rely
upon a client's behavior, e.g., the [=[RP]=] SHOULD store the challenge temporarily
until the operation is complete. Tolerating a mismatch will compromise the security
of the protocol.

Challenges SHOULD be valid for a duration similar to the
upper limit of the [=recommended range and default for a WebAuthn ceremony timeout=].

In order to prevent replay attacks, the challenges MUST contain enough entropy to make guessing them infeasible. Challenges SHOULD
therefore be at least 16 bytes long.


### Attestation Limitations ### {#sctn-attestation-limitations}

[INFORMATIVE]

When [[#sctn-registering-a-new-credential|registering a new credential]], the [=attestation statement=], if present,
may allow the [=[WRP]=] to derive assurances about various [=authenticator=] qualities.
For example, the [=authenticator=] model, or how it stores and protects [=credential private keys=].
However, it is important to note that an [=attestation statement=], on its own,
provides no means for a [=[RP]=] to verify that an [=attestation object=] was generated
by the [=authenticator=] the user intended, and not by a [=man-in-the-middle attack|man-in-the-middle attacker=].
For example, such an attacker could use malicious code injected into [=[RP]=] script.
The [=[RP]=] must therefore rely on other means, e.g., TLS and related technologies,
to protect the [=attestation object=] from [=man-in-the-middle attacks=].

Under the assumption that a [=registration ceremony=] is completed securely, and that the [=authenticator=] maintains
confidentiality of the [=credential private key=], subsequent [=authentication ceremonies=] using that [=public key
credential=] are resistant to tampering by [=man-in-the-middle attacks=].

The discussion above holds for all [=attestation types=]. In all cases it is possible for a [=man-in-the-middle
attack|man-in-the-middle attacker=] to replace the {{PublicKeyCredential}} object, including the [=attestation statement=] and the
[=credential public key=] to be registered, and subsequently tamper with future [=authentication assertions=] [=scoped=] for the
same [=[RP]=] and passing through the same attacker.

Such an attack would potentially be detectable; since the [=[RP]=] has registered the attacker's [=credential public key=] rather
than the user's, the attacker must tamper with all subsequent [=authentication ceremonies=] with that [=[RP]=]: unscathed
ceremonies will fail, potentially revealing the attack.

[=Attestation types=] other than [=Self Attestation=] and [=None=] can increase the difficulty of such attacks, since [=[RPS]=]
can possibly display [=authenticator=] information, e.g., model designation, to the user. An attacker might therefore need to use
a genuine [=authenticator=] of the same model as the user's [=authenticator=], or the user might notice that the [=[RP]=] reports
a different [=authenticator=] model than the user expects.

Note: All variants of [=man-in-the-middle attacks=] described above are more difficult for an attacker to mount
than a [=man-in-the-middle attack=] against conventional password authentication.


### Revoked Attestation Certificates ### {#sctn-revoked-attestation-certificates}

If [=attestation certificate=] validation fails due to a revoked intermediate attestation CA certificate, and the [=[RP]=]'s policy
requires rejecting the registration/authentication request in these situations, then it is RECOMMENDED that the [=[RP]=] also
un-registers (or marks with a trust level equivalent to "[=self attestation=]") [=public key credentials=] that were registered
after the CA compromise date using an [=attestation certificate=] chaining up to the same intermediate CA. It is thus RECOMMENDED
that [=[RPS]=] remember intermediate attestation CA certificates during [=registration=] in order to un-register
related [=public key credentials=] if the [=registration=] was performed after revocation of such certificates.

See also the related security consideration for [=authenticators=] in [[#sctn-ca-compromise]].


### Credential Loss and Key Mobility ### {#sctn-credential-loss-key-mobility}

This specification defines no protocol for backing up [=credential private keys=], or for sharing them between [=authenticators=].
In general, it is expected that a [=credential private key=] never leaves the [=authenticator=] that created it. Losing an
[=authenticator=] therefore, in general, means losing all [=public key credential|credentials=] [=bound credential|bound=] to the
lost [=authenticator=], which could lock the user out of an account if the user has only one [=public key credential|credential=]
registered with the [=[RP]=]. Instead of backing up or sharing private keys, the Web Authentication API allows registering
multiple [=public key credential|credentials=] for the same user. For example, a user might register [=platform credentials=] on
frequently used [=client devices=], and one or more [=roaming credentials=] for use as backup and with new or rarely used [=client
devices=].

[=[RPS]=] SHOULD allow and encourage users to register multiple [=public key credential|credentials=] to the same [=user account=].
[=[RPS]=] SHOULD make use of the <code>{{PublicKeyCredentialCreationOptions/excludeCredentials}}</code> and
<code>{{PublicKeyCredentialCreationOptions/user}}.{{PublicKeyCredentialUserEntity/id}}</code> options to ensure that these
different [=public key credential|credentials=] are [=bound credential|bound=] to different [=authenticators=].


### Unprotected account detection ### {#sctn-unprotected-account-detection}

[INFORMATIVE]

This security consideration applies to [=[RPS]=] that support [=authentication ceremonies=]
with a non-[=list/empty=] {{PublicKeyCredentialRequestOptions/allowCredentials}} argument as the first authentication step.
For example, if using authentication with [=server-side credentials=] as the first authentication step.

In this case the {{PublicKeyCredentialRequestOptions/allowCredentials}} argument risks leaking information
about which [=user accounts=] have WebAuthn credentials registered and which do not,
which may be a signal of account protection strength.
For example, say an attacker can initiate an [=authentication ceremony=] by providing only a username,
and the [=[RP]=] responds with a non-empty {{PublicKeyCredentialRequestOptions/allowCredentials}} for some [=user accounts=],
and with failure or a password challenge for other [=user accounts=].
The attacker can then conclude that the latter [=user accounts=]
likely do not require a WebAuthn [=assertion=] for successful authentication,
and thus focus an attack on those likely weaker accounts.

This issue is similar to the one described in [[#sctn-username-enumeration]]
and [[#sctn-credential-id-privacy-leak]], and can be mitigated in similar ways.


### Code injection attacks ### {#sctn-code-injection}

Any malicious code executing on an
[=determines the set of origins on which the public key credential may be exercised|origin=]
within the [=scope=] of a [=[RP]=]'s [=public key credentials=]
has the potential to invalidate any and all security guarantees WebAuthn may provide.
[=[WAC]s=] only expose the WebAuthn API in [=secure contexts=],
which mitigates the most basic attacks but SHOULD be combined with additional precautions by [=[RPS]=].

Code injection can happen in several ways;
this section attempts to point out some likely scenarios and suggest suitable mitigations,
but is not an exhaustive list.

  - Malicous code could be injected by a third-party script included by the [=[RP]=],
    either intentionally or due to a security vulnerability in the third party.

    The [=[RP]=] therefore SHOULD limit the amount of third-party script included on the
    [=determines the set of origins on which the public key credential may be exercised|origins=]
    within the [=scope=] of its [=credentials=].

    The [=[RP]=] SHOULD use Content Security Policy [[!CSP2]],
    and/or other appropriate technologies available at the time, to limit what script can run on its
    [=determines the set of origins on which the public key credential may be exercised|origins=].

  - Malicious code could, by the credential [=scope=] rules, be hosted on a subdomain of the [=RP ID=].
    For example, user-submitted code hosted on `usercontent.example.org`
    could exercise any [=credentials=] [=scoped=] to the [=RP ID=] `example.org`.
    If the [=[RP]=] allows a subdomain {{CollectedClientData/origin}}
    when [verifying the assertion](#rp-op-verifying-assertion-step-origin),
    malicious users could use this to launch a [=man-in-the-middle attack=]
    to obtain valid [=authentication assertions=] and impersonate the victims of the attack.

    Therefore, the [=[RP]=] by default SHOULD NOT allow a subdomain {{CollectedClientData/origin}}
    when [verifying the assertion](#rp-op-verifying-assertion-step-origin).
    If the [=[RP]=] needs to allow a subdomain {{CollectedClientData/origin}},
    then the [=[RP]=] MUST NOT serve untrusted code on any allowed subdomain of
    [=determines the set of origins on which the public key credential may be exercised|origins=]
    within the [=scope=] of its [=public key credentials=].


### Validating the origin of a credential ### {#sctn-validating-origin}

When [registering a credential](#rp-op-registering-a-new-credential-step-origin) and
when [verifying an assertion](#rp-op-verifying-assertion-step-origin),
the [=[RP]=] MUST validate the {{CollectedClientData/origin}} member of the [=client data=].

The [=[RP]=] MUST NOT accept unexpected values of {{CollectedClientData/origin}},
as doing so could allow a malicious website to obtain valid [=credentials=].
Although the [=scope=] of WebAuthn credentials prevents their use on domains
outside the [=RP ID=] they were registered for,
the [=[RP]=]'s origin validation serves as an additional layer of protection
in case a faulty [=authenticator=] fails to enforce credential [=scope=].
See also [[#sctn-code-injection]] for discussion of potentially malicious subdomains.

Validation MAY be performed by exact string matching or any other method as needed by the [=[RP]=].
For example:

- A web application served only at <code>https://example.org</code> SHOULD require
    {{CollectedClientData/origin}} to exactly equal <code>https://example.org</code>.

    This is the simplest case, where {{CollectedClientData/origin}} is expected
    to be the string <code>https://</code> followed by the [=RP ID=].

- A web application served at a small number of domains might require
    {{CollectedClientData/origin}} to exactly equal some element of a list of allowed origins,
    for example the list <code>["https://example.org", "https://login.example.org"]</code>.

- A web application leveraging [[#sctn-related-origins|related origin requests]] might also require
    {{CollectedClientData/origin}} to exactly equal some element of a list of allowed origins,
    for example the list <code>["https://example.co.uk", "https://example.de", "https://myexamplerewards.com"]</code>.
    This list will typically match the origins listed in the well-known URI for the [=RP ID=]. See [[#sctn-related-origins]].

- A web application served at a large set of domains that changes often might parse
    {{CollectedClientData/origin}} structurally and require that the URL scheme is <code>https</code>
    and that the authority equals or is any subdomain of the [=RP ID=] - for example,
    <code>example.org</code> or any subdomain of <code>example.org</code>).

    Note: See [[#sctn-code-injection]] for a discussion of the risks of allowing any subdomain of the [=RP ID=].

- A web application with a companion native application might allow
    {{CollectedClientData/origin}} to be an operating system dependent
    identifier for the native application. For example, such a [=[RP]=] might require that
    {{CollectedClientData/origin}} exactly equals some element of the list
    <code>["https://example.org", "example-os:appid:204ffa1a5af110ac483f131a1bef8a841a7adb0d8d135908bbd964ed05d2653b"]</code>.

Similar considerations apply when validating the {{CollectedClientData/topOrigin}} member of the [=client data=].
When {{CollectedClientData/topOrigin}} is present, the [=[RP]=] MUST validate that its value is expected.
This validation MAY be performed by exact string matching or any other method as needed by the [=[RP]=].
For example:

- A web application that does not wish to be embedded in a cross-origin <{iframe}>
    might require {{CollectedClientData/topOrigin}} to exactly equal {{CollectedClientData/origin}}.

- A web application that wishes to be embedded in a cross-origin <{iframe}> on a small number of domains
    might require {{CollectedClientData/topOrigin}} to exactly equal some element of a list of allowed origins,
    for example the list <code>["https://example-partner1.org", "https://login.partner2-example.org"]</code>.

- A web application that wishes to be embedded in a cross-origin <{iframe}> on a large number of domains
    might allow any value of {{CollectedClientData/topOrigin}}, or use a dynamic procedure
    to determine whether a given {{CollectedClientData/topOrigin}} value is allowed for a particular ceremony.


# Privacy Considerations # {#sctn-privacy-considerations}

The privacy principles in [[!FIDO-Privacy-Principles]] also apply to this specification.

This section is divided by audience;
general privacy considerations are direct subsections of this section,
while privacy considerations specifically for [=authenticator=], [=client=] and [=[RP]=] implementers
are grouped into respective subsections.


## De-anonymization Prevention Measures ## {#sctn-privacy-attacks}

[INFORMATIVE]

Many aspects of the design of the [=Web Authentication API=] are motivated by privacy concerns. The main concern considered in
this specification is the protection of the user's personal identity, i.e., the identification of a human being or a correlation
of separate identities as belonging to the same human being. Although the [=Web Authentication API=] does not use or provide any
form of global identity, the following kinds of potentially correlatable identifiers are used:

- The user's [=credential IDs=] and [=credential public keys=].

    These are registered by the [=[WRP]=] and subsequently used by the user to prove possession of the corresponding [=credential
    private key=]. They are also visible to the [=client=] in the communication with the [=authenticator=].

- The user's identities specific to each [=[RP]=], e.g., usernames and [=user handles=].

    These identities are obviously used by each [=[RP]=] to identify a user in their system. They are also visible to the
    [=client=] in the communication with the [=authenticator=].

- The user's biometric characteristic(s), e.g., fingerprints or facial recognition data [[ISOBiometricVocabulary]].

    This is optionally used by the [=authenticator=] to perform [=user verification=]. It is not revealed to the [=[RP]=], but in
    the case of [=platform authenticators=], it might be visible to the [=client=] depending on the implementation.

- The models of the user's [=authenticators=], e.g., product names.

    This is exposed in the [=attestation statement=] provided to the [=[RP]=] during [=registration=]. It is also visible to the
    [=client=] in the communication with the [=authenticator=].

- The identities of the user's [=authenticators=], e.g., serial numbers.

    This is possibly used by the [=client=] to enable communication with the [=authenticator=], but is not exposed to the
    [=[RP]=].

Some of the above information is necessarily shared with the [=[RP]=]. The following sections describe the measures taken to
prevent malicious [=[RPS]=] from using it to discover a user's personal identity.


## Anonymous, Scoped, Non-correlatable [=Public Key Credentials=] ## {#sctn-non-correlatable-credentials}

[INFORMATIVE]

Although [=Credential IDs=] and [=credential public keys=] are necessarily shared with the [=[WRP]=] to enable strong
authentication, they are designed to be minimally identifying and not shared between [=[RPS]=].

- [=Credential IDs=] and [=credential public keys=] are meaningless in isolation, as they only identify [=credential key pairs=]
    and not users directly.

- Each [=public key credential=] is strictly [=scoped=] to a specific [=[RP]=], and the [=client=] ensures that its existence is not
    revealed to other [=[RPS]=]. A malicious [=[RP]=] thus cannot ask the [=client=] to reveal a user's other identities.

- The [=client=] also ensures that the existence of a [=public key credential=] is not revealed to the [=[RP]=] without [=user
    consent=]. This is detailed further in [[#sctn-make-credential-privacy]] and [[#sctn-assertion-privacy]]. A malicious [=[RP]=]
    thus cannot silently identify a user, even if the user has a [=public key credential=] registered and available.

- [=Authenticators=] ensure that the [=credential IDs=] and [=credential public keys=] of different [=public key credentials=] are
    not correlatable as belonging to the same user. A pair of malicious [=[RPS]=] thus cannot correlate users between their
    systems without additional information, e.g., a willfully reused username or e-mail address.

- [=Authenticators=] ensure that their [=attestation certificates=] are not unique enough to identify a single [=authenticator=]
    or a small group of [=authenticators=]. This is detailed further in [[#sctn-attestation-privacy]]. A pair of malicious
    [=[RPS]=] thus cannot correlate users between their systems by tracking individual [=authenticators=].

Additionally, a [=client-side discoverable public key credential source=] can optionally include a [=user
handle=] specified by the [=[RP]=]. The [=public key credential|credential=] can then be used to both identify and
[=authentication|authenticate=] the user.
This means that a privacy-conscious [=[RP]=] can allow creation of a [=user account=] without a traditional username,
further improving non-correlatability between [=[RPS]=].


## Authenticator-local [=Biometric Recognition=] ## {#sctn-biometric-privacy}

[=Biometric authenticators=] perform the [=biometric recognition=] internally in the [=authenticator=] - though for [=platform
authenticators=] the biometric data might also be visible to the [=client=], depending on the implementation. Biometric data is
not revealed to the [=[WRP]=]; it is used only locally to perform [=user verification=] authorizing the creation and
[=registration=] of, or [=authentication=] using, a [=public key credential=]. A malicious [=[RP]=] therefore cannot discover the
user's personal identity via biometric data, and a security breach at a [=[RP]=] cannot expose biometric data for an attacker to
use for forging logins at other [=[RPS]=].

In the case where a [=[RP]=] requires [=biometric recognition=], this is performed locally by the [=biometric authenticator=]
perfoming [=user verification=] and then signaling the result by setting the [=authData/flags/UV=] [=flag=] in the signed [=assertion=] response,
instead of revealing the biometric data itself to the [=[RP]=].


## Privacy considerations for [=authenticators=] ## {#sctn-privacy-considerations-authenticator}

### Attestation Privacy ### {#sctn-attestation-privacy}

[=Attestation certificates=] and [=attestation key pairs=] can be used to track users
or link various online identities of the same user together.
This can be mitigated in several ways, including:

- A [=[WAA]=] manufacturer may choose to ship [=authenticators=] in batches
    where [=authenticators=] in a batch share the same [=attestation certificate=] (called [=Basic Attestation=] or [=batch attestation=]).
    This will anonymize the user at the risk of not being able to revoke a particular [=attestation certificate=]
    if its [=attestation private key|private key=] is compromised.
    The [=authenticator=] manufacturer SHOULD then ensure that such batches are large enough to provide meaningful anonymization,
    while also minimizing the batch size in order to limit the number of affected users
    in case an [=attestation private key=] is compromised.

    [[UAFProtocol]] requires that at least 100,000 [=authenticator=] devices share the same [=attestation certificate=] in order to produce
    sufficiently large groups. This may serve as guidance about suitable batch sizes.

- A [=[WAA]=] may be capable of dynamically generating different [=attestation key pairs=] (and requesting related
    [=attestation certificate|certificates=]) per-[=credential=] as described in the [=Anonymization CA=] approach. For example, an [=authenticator=] can ship with a
    main [=attestation private key=] (and [=attestation certificate|certificate=]),
    and combined with a cloud-operated [=Anonymization CA=],
    can dynamically generate per-[=credential=] [=attestation key pairs=] and [=attestation certificates=].

    Note: In various places outside this specification, the term "Privacy CA" is used to refer to what is termed here
        as an [=Anonymization CA=]. Because the Trusted Computing Group (TCG) also used the term "Privacy CA" to refer to what
        the TCG now refers to as an [=Attestation CA=] (ACA) [[!TCG-CMCProfile-AIKCertEnroll]], we are using the term [=Anonymization CA=] here to try to mitigate
        confusion in the specific context of this specification.


### Privacy of [PII] Stored in Authenticators ### {#sctn-pii-privacy}

[=Authenticators=] MAY provide additional information to [=clients=] outside what's defined by this specification, e.g.,
to enable the [=client=] to provide a rich UI with which the user can pick which [=credential=] to use for an [=authentication
ceremony=]. If an [=authenticator=] chooses to do so, it SHOULD NOT expose [PII] unless successful [=user verification=] has been
performed. If the [=authenticator=] supports [=user verification=] with more than one concurrently enrolled user, the
[=authenticator=] SHOULD NOT expose [PII] of users other than the currently [=user verified|verified=] user. Consequently, an
[=authenticator=] that is not capable of [=user verification=] SHOULD NOT store [PII].

For the purposes of this discussion, the [=user handle=] conveyed as the {{PublicKeyCredentialUserEntity/id}} member of
{{PublicKeyCredentialUserEntity}} is not considered [PII]; see [[#sctn-user-handle-privacy]].

These recommendations serve to prevent an adversary with physical access to an [=authenticator=] from extracting [PII] about the
[=authenticator=]'s enrolled user(s).


## Privacy considerations for [=clients=] ## {#sctn-privacy-considerations-client}

### Registration Ceremony Privacy ### {#sctn-make-credential-privacy}

In order to protect users from being identified without [=user consent|consent=], implementations of the
{{PublicKeyCredential/[CREATE-METHOD]}} method need to take care to not leak information that
could enable a malicious [=[WRP]=] to distinguish between these cases, where "excluded" means that at least one of the [=public key
credential|credentials=] listed by the [=[RP]=] in {{PublicKeyCredentialCreationOptions/excludeCredentials}} is [=bound credential|bound=] to the
[=authenticator=]:

- No [=authenticators=] are present.
- At least one [=authenticator=] is present, and at least one present [=authenticator=] is excluded.

If the above cases are distinguishable, information is leaked by which a malicious [=[RP]=] could identify the user by probing for
which [=public key credential|credentials=] are available. For example, one such information leak is if the client returns a
failure response as soon as an excluded [=authenticator=] becomes available. In this case - especially if the excluded
[=authenticator=] is a [=platform authenticator=] - the [=[RP]=] could detect that the [=ceremony=] was canceled
before the user could feasibly have canceled it manually, and thus conclude that at least one of the [=public key
credential|credentials=] listed in the {{PublicKeyCredentialCreationOptions/excludeCredentials}} parameter is available to the user.

The above is not a concern, however, if the user has [=user consent|consented=] to create a new credential before a
distinguishable error is returned, because in this case the user has confirmed intent to share the information that would be
leaked.


### Authentication Ceremony Privacy ### {#sctn-assertion-privacy}

In order to protect users from being identified without [=user consent|consent=], implementations of the
{{PublicKeyCredential/[DISCOVER-METHOD]}} method need to take care to not
leak information that could enable a malicious [=[WRP]=] to distinguish between these cases, where "named" means that the [=public
key credential|credential=] is listed by the [=[RP]=] in {{PublicKeyCredentialRequestOptions/allowCredentials}}:

- A named [=public key credential|credential=] is not available.
- A named [=public key credential|credential=] is available, but the user does not [=user consent|consent=] to use it.

If the above cases are distinguishable, information is leaked by which a malicious [=[RP]=] could identify the user by probing
for which [=public key credential|credentials=] are available.
For example, one such information leak may happen if the client displays instructions and controls
for canceling or proceeding with the [=authentication ceremony=]
only after discovering an [=authenticator=] that [=contains=] a named [=credential=].
In this case, if the [=[RP]=] is aware of this [=client=] behavior,
the [=[RP]=] could detect that the [=ceremony=] was canceled by the user and not the timeout, and thus conclude that at least
one of the [=public key credential|credentials=] listed in the {{PublicKeyCredentialRequestOptions/allowCredentials}} parameter is
available to the user.

This concern may be addressed by displaying controls allowing the user to cancel an [=authentication ceremony=] at any time,
regardless of whether any named [=credentials=] are available.


### Privacy Between Operating System Accounts ### {#sctn-os-account-privacy}

If a [=platform authenticator=] is included in a [=client device=] with a multi-user operating system, the [=platform
authenticator=] and [=client device=] SHOULD work together to ensure that the existence of any [=platform credential=] is revealed
only to the operating system user that created that [=platform credential=].

### Disclosing Client Capabilities ### {#sctn-disclosing-client-capabilities}

The {{getClientCapabilities}} method assists [=[WRPS]=] in crafting registration and authentication experiences which have a high chance of success with the client and/or user.

A [=WebAuthn Client's=] support or lack of support of a capability may pose a fingerprinting risk. To reduce this risk, clients SHOULD prefer to omit a key from the returned record rather than returning a value of false. Omitting the key (as described in [[#sctn-getClientCapabilities]]) provides less fingerprinting surface than explicitly confirming a feature is unsupported. Client implementations MAY also wish to limit capability disclosures based on client policy and/or user consent.

## Privacy considerations for [=[RPS]=] ## {#sctn-privacy-considerations-rp}

### User Handle Contents ### {#sctn-user-handle-privacy}

Since the [=user handle=] is not considered [PII] in [[#sctn-pii-privacy]],
and since [=authenticators=] MAY reveal [=user handles=] without first performing [=user verification=],
the [=[RP]=] MUST NOT include [PII], e.g., e-mail
addresses or usernames, in the [=user handle=]. This includes hash values of [PII], unless the hash
function is [=salted=] with [=salt=] values private to the [=[RP]=], since hashing does not prevent probing for guessable input
values. It is RECOMMENDED to let the [=user handle=] be 64 random bytes, and store this value in the [=user account=].


### Username Enumeration ### {#sctn-username-enumeration}

While initiating a [=registration ceremony|registration=] or [=authentication ceremony=], there is a risk that the [=[WRP]=] might leak sensitive
information about its registered users. For example, if a [=[RP]=] uses e-mail addresses as usernames and an attacker attempts to
initiate an [=authentication=] [=ceremony=] for "alex.mueller@example.com" and the [=[RP]=] responds with a failure, but then
successfully initiates an [=authentication ceremony=] for "j.doe@example.com", then the attacker can conclude that "j.doe@example.com"
is registered and "alex.mueller@example.com" is not. The [=[RP]=] has thus leaked the possibly sensitive information that
"j.doe@example.com" has a [=user account=] at this [=[RP]=].

The following is a non-normative, non-exhaustive list of measures the [=[RP]=] may implement to mitigate or prevent information
leakage due to such an attack:

- For [=registration ceremonies=]:

    - If the [=[RP]=] uses [=[RP]=]-specific usernames to identify users:

        - When initiating a [=registration ceremony=], disallow registration of usernames that are syntactically valid e-mail
            addresses.

            Note: The motivation for this suggestion is that in this case the [=[RP]=] probably has no choice but to fail the
            [=registration ceremony=] if the user attempts to register a username that is already registered, and an information
            leak might therefore be unavoidable. By disallowing e-mail addresses as usernames, the impact of the leakage can be
            mitigated since it will be less likely that a user has the same username at this [=[RP]=] as at other [=[RPS]=].

    - If the [=[RP]=] uses e-mail addresses to identify users:

        - When initiating a [=registration ceremony=], interrupt the user interaction after the e-mail address is supplied and
            send a message to this address, containing an unpredictable one-time code and instructions for how to use it to
            proceed with the ceremony. Display the same message to the user in the web interface regardless of the contents of the
            sent e-mail and whether or not this e-mail address was already registered.

            Note: This suggestion can be similarly adapted for other externally meaningful identifiers, for example, national ID
            numbers or credit card numbers &mdash; if they provide similar out-of-band contact information, for example,
            conventional postal address.

- For [=authentication ceremonies=]:

    - If, when initiating an [=authentication ceremony=], there is no [=user account=] matching the provided username, continue the
        ceremony by invoking {{CredentialsContainer/get()|navigator.credentials.get()}} using a syntactically valid
        {{PublicKeyCredentialRequestOptions}} object that is populated with plausible imaginary values.

        This approach could also be used to mitigate information leakage via {{PublicKeyCredentialRequestOptions/allowCredentials}};
        see [[#sctn-unprotected-account-detection]] and [[#sctn-credential-id-privacy-leak]].

        Note: The username may be "provided" in various [=[RP]=]-specific fashions: login form, session cookie, etc.

        Note: If returned imaginary values noticeably differ from actual ones, clever attackers may be able to discern them and
            thus be able to test for existence of actual accounts. Examples of noticeably different values include if the values
            are always the same for all username inputs, or are different in repeated attempts with the same username input. The
            {{PublicKeyCredentialRequestOptions/allowCredentials}} member could therefore be populated with pseudo-random values
            derived deterministically from the username, for example.

    - When verifying an {{AuthenticatorAssertionResponse}} response from the [=authenticator=], make it indistinguishable whether
          verification failed because the signature is invalid or because no such user or credential is registered.

    - Perform a multi-step [=authentication ceremony=], e.g., beginning with supplying username and password or a session cookie,
        before initiating the WebAuthn [=ceremony=] as a subsequent step.
        This moves the username enumeration problem from the WebAuthn step
        to the preceding authentication step, where it may be easier to solve.


### Privacy leak via credential IDs ### {#sctn-credential-id-privacy-leak}

[INFORMATIVE]

This privacy consideration applies to [=[RPS]=] that support [=authentication ceremonies=]
with a non-[=list/empty=] {{PublicKeyCredentialRequestOptions/allowCredentials}} argument as the first authentication step.
For example, if using authentication with [=server-side credentials=] as the first authentication step.

In this case the {{PublicKeyCredentialRequestOptions/allowCredentials}} argument risks leaking [PII],
since it exposes the user's [=credential IDs=] to an unauthenticated caller.
[=Credential IDs=] are designed to not be correlatable between [=[RPS]=],
but the length of a [=credential ID=] might be a hint as to what type of [=authenticator=] created it.
It is likely that a user will use the same username and set of [=authenticators=] for several [=[RPS]=],
so the number of [=credential IDs=] in {{PublicKeyCredentialRequestOptions/allowCredentials}} and their lengths
might serve as a global correlation handle to de-anonymize the user.
Knowing a user's [=credential IDs=] also makes it possible to confirm guesses about the user's identity
given only momentary physical access to one of the user's [=authenticators=].

In order to prevent such information leakage, the [=[RP]=] could for example:

- Perform a separate authentication step,
    such as username and password authentication or session cookie authentication,
    before initiating the WebAuthn [=authentication ceremony=] and exposing the user's [=credential IDs=].
- Use [=client-side discoverable credentials=],
    so the {{PublicKeyCredentialRequestOptions/allowCredentials}} argument is not needed.

If the above prevention measures are not available,
i.e., if {{PublicKeyCredentialRequestOptions/allowCredentials}} needs to be exposed given only a username,
the [=[RP]=] could mitigate the privacy leak using the same approach of returning imaginary [=credential IDs=]
as discussed in [[#sctn-username-enumeration]].

When [=signal methods|signalling=] that a [=credential id=] was not recognized,
the [=[WRP]=] SHOULD use the
{{PublicKeyCredential/signalUnknownCredential(options)}} method instead of the
{{PublicKeyCredential/signalAllAcceptedCredentials(options)}} method to avoid
exposing [=credential IDs=] to an unauthenticated caller.

# Accessibility Considerations # {#sctn-accessiblility-considerations}

[=User verification=]-capable [=authenticators=], whether [=roaming authenticators|roaming=] or [=platform authenticators|platform=], should offer users more than one user verification method.  For example, both fingerprint sensing and PIN entry. This allows for fallback to other user verification means if the selected one is not working for some reason. Note that in the case of [=roaming authenticators=], the authenticator and platform might work together to provide a user verification method such as PIN entry [[FIDO-CTAP]].

[=[RPS]=], at [=registration=] time, SHOULD provide affordances for users to complete future [=authorization gestures=] correctly. This could involve naming the authenticator, choosing a picture to associate with the device, or entering freeform text instructions (e.g., as a reminder-to-self).


## Recommended Range for Ceremony Timeouts ## {#sctn-timeout-recommended-range}

[=Ceremonies=] relying on timing, e.g., a [=registration ceremony=] (see {{PublicKeyCredentialCreationOptions/timeout}}) or an [=authentication ceremony=] (see {{PublicKeyCredentialRequestOptions/timeout}}), ought to follow [[!WCAG21]]'s [Guideline 2.2 Enough Time](https://www.w3.org/TR/WCAG21/#enough-time). If a [=client platform=] determines that a [=[RP]=]-supplied timeout does not appropriately adhere to the latter [[!WCAG21]] guidelines, then the [=client platform=] MAY adjust the timeout accordingly.

The <dfn>recommended range and default for a WebAuthn ceremony timeout</dfn> is as follows:

* Recommended range: 300000 milliseconds to 600000 milliseconds.
* Recommended default value: 300000 milliseconds (5 minutes).


# Test Vectors # {#sctn-test-vectors}

[INFORMATIVE]

This section lists example values that may be used to validate implementations.

Examples are given as pseudocode in pairs of [=registration ceremony|registration=]
and [=authentication ceremonies=] done with the same [=credential=],
with byte string literals and comments in CDDL [[RFC8610]] notation.
The examples are not exhaustive and do not include [=WebAuthn extensions=].

The examples are structured as a flow from inputs to outputs, including some intermediate values.
In registration examples the [=[RP]=] defines the {{PublicKeyCredentialCreationOptions/challenge}} input,
the [=client=] generates the {{AuthenticatorResponse/clientDataJSON}} output
and the [=authenticator=] generates the {{AuthenticatorAttestationResponse/attestationObject}} output.
In authentication examples the [=[RP]=] defines the {{PublicKeyCredentialRequestOptions/challenge}} input,
the [=client=] generates the {{AuthenticatorResponse/clientDataJSON}} output
and the [=authenticator=] generates the
{{AuthenticatorAssertionResponse/authenticatorData}} and {{AuthenticatorAssertionResponse/signature}} outputs.
Other cryptographically unrelated inputs and outputs are not included.

[=Authenticator=] implementers may check that they produce similarly structured
{{AuthenticatorAttestationResponse/attestationObject}},
{{AuthenticatorAssertionResponse/authenticatorData}} and {{AuthenticatorAssertionResponse/signature}} outputs.
[=Client=] implementers may check that they produce similarly structured {{AuthenticatorResponse/clientDataJSON}} outputs.
[=[RP]=] implementers may check that they can successfully validate the registration outputs
given the same {{PublicKeyCredentialCreationOptions/challenge}} input,
and that they can successfully validate the authentication outputs
given the same {{PublicKeyCredentialRequestOptions/challenge}} input
and the [=credential public key=] and [=credential ID=] from the associated registration example.

All examples use the [=RP ID=] `example.org`, the {{CollectedClientData/origin}} `https://example.org`
and, where applicable, the {{CollectedClientData/topOrigin}} `https://example.com`.
Examples include [=None|no attestation=] when not noted otherwise.
Note that composite objects such as `clientDataJSON`, `attestationObject` and attestation certificates
may contain additional, usually constant, data not mentioned explicitly in the pseudocode.

All random values are deterministically generated using HKDF-SHA-256 [[RFC5869]]
from the base input key material denoted in CDDL as `'WebAuthn test vectors'`,
or equivalently as `h'576562417574686e207465737420766563746f7273'`.
ECDSA signatures use a deterministic nonce [[RFC6979]].
The RSA key in the examples is constructed from the two smallest Mersenne primes 2<sup>p</sup> - 1 such that p &ge; 1024.

Note that:

- Although the examples include [=credential private keys=] and [=attestation private keys=] for reproducibility,
    these would normally not be shared with the [=client=] or [=[RP]=].
- Although each example uses a different [=/AAGUID=], the [=/AAGUID=] would normally be constant for a given [=authenticator=].

Note: [=Authenticators=] implementing CTAP2 [[FIDO-CTAP]] return [=attestation objects=]
using different keys than those defined in this specification.
These examples reflect the attestation object format expected by [=[WRPS]=],
so [=attestation objects=] emitted from CTAP2 need their keys translated
in order to be bitwise identical to these examples.


<!-- GENERATED CONTENT: Use test-vectors/webauthn-test-vectors.py -->
## Attestation trust root certificate ## {#sctn-test-vectors-attestation-root-cert}

All examples that include [=attestation=] use the attestation trust root certificate
given as `attestation_ca_cert` below, encoded in X.509 DER [[RFC5280]]:

<xmp class="example" highlight="cddl">
attestation_ca_key = h'7809337f05740a96a78eedf9e9280499dcc8f2aa129616049ec1dccfe103eb2a'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='Attestation CA', L=32)
attestation_ca_serial_number = h'ed7f905d8bd0b414d1784913170a90b6'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='Attestation CA', L=16)
attestation_ca_cert = h'30820207308201ada003020102021100ed7f905d8bd0b414d1784913170a90b6300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a3062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d030107034200043269300e5ff7b699015f70cf80a8763bf705bc2e2af0c1b39cff718b7c35880ca30f319078d91b03389a006fdfc8a1dcd84edfa07d30aa13474a248a0dab5baaa3423040300f0603551d130101ff040530030101ff300e0603551d0f0101ff040403020106301d0603551d0e0416041445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d04030203480030450220483063b6bb08dcc83da33a02c11d2f42203176893554d138c614a36908724cc8022100f5ef2c912d4500b3e2f5b591d0622491e9f220dfd1f9734ec484bb7e90887663'
</xmp>


## ES256 Credential with No Attestation ## {#sctn-test-vectors-none-es256}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'00c30fb78531c464d2b6771dab8d7b603c01162f2fa486bea70f283ae556e130'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='none.ES256', L=32)

credential_private_key = h'6e68e7a58484a3264f66b77f5d6dc5bc36a47085b615c9727ab334e8c369c2ee'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='none.ES256', L=32)
client_data_gen_flags = h'f9'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='none.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'06441e0e375c4c1ad70620302532c4e5' = b64'BkQeDjdcTBrXBiAwJTLE5Q'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='none.ES256', L=16)
aaguid = h'8446ccb9ab1db374750b2367ff6f3a1f'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='none.ES256', L=16)
credential_id = h'f91f391db4c9b2fde0ea70189cba3fb63f579ba6122b33ad94ff3ec330084be4'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='none.ES256', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'ba'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='none.ES256', L=1)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22414d4d507434557878475453746e63647134313759447742466938767049612d7077386f4f755657345441222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20426b5165446a646354427258426941774a544c453551227d'
attestationObject = h'a363666d74646e6f6e656761747453746d74a068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b559000000008446ccb9ab1db374750b2367ff6f3a1f0020f91f391db4c9b2fde0ea70189cba3fb63f579ba6122b33ad94ff3ec330084be4a5010203262001215820afefa16f97ca9b2d23eb86ccb64098d20db90856062eb249c33a9b672f26df61225820930a56b87a2fca66334b03458abf879717c12cc68ed73290af2e2664796b9220'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'39c0e7521417ba54d43e8dc95174f423dee9bf3cd804ff6d65c857c9abf4d408'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='none.ES256', L=32)

client_data_gen_flags = h'4a'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='none.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'38'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='none.ES256', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a224f63446e55685158756c5455506f334a5558543049393770767a7a59425039745a63685879617630314167222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
signature = h'3046022100f50a4e2e4409249c4a853ba361282f09841df4dd4547a13a87780218deffcd380221008480ac0f0b93538174f575bf11a1dd5d78c6e486013f937295ea13653e331e87'
</xmp>


## ES256 Credential with Self Attestation ## {#sctn-test-vectors-packed-self-es256}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'7869c2b772d4b58eba9378cf8f29e26cf935aa77df0da89fa99c0bdc0a76f7e5'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed-self.ES256', L=32)

credential_private_key = h'b4bbfa5d68e1693b6ef5a19a0e60ef7ee2cbcac81f7fec7006ac3a21e0c5116a'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed-self.ES256', L=32)
client_data_gen_flags = h'db'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed-self.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'53d8535ef284d944643276ffd3160756' = b64'U9hTXvKE2URkMnb_0xYHVg'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed-self.ES256', L=16)
aaguid = h'df850e09db6afbdfab51697791506cfc'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed-self.ES256', L=16)
credential_id = h'455ef34e2043a87db3d4afeb39bbcb6cc32df9347c789a865ecdca129cbef58c'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed-self.ES256', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'fd'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed-self.ES256', L=1)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a2265476e4374334c55745936366b336a506a796e6962506b31716e666644616966715a774c33417032392d55222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a205539685458764b453255526b4d6e625f307859485667227d'
attestationObject = h'a363666d74667061636b65646761747453746d74a263616c672663736967584630440220067a20754ab925005dbf378097c92120031581c73228d1fb4f5b881bcd7da98302207fc7b147558c7c0eba3af18bd9d121fa3d3a26d17fe3f220272178f473b6006d68617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55d00000000df850e09db6afbdfab51697791506cfc0020455ef34e2043a87db3d4afeb39bbcb6cc32df9347c789a865ecdca129cbef58ca5010203262001215820eb151c8176b225cc651559fecf07af450fd85802046656b34c18f6cf193843c5225820927b8aa427a2be1b8834d233a2d34f61f13bfd44119c325d5896e183fee484f2'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'4478a10b1352348dd160c1353b0d469b5db19eb91c27f7dfa6fed39fe26af20b'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed-self.ES256', L=32)

client_data_gen_flags = h'1f'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed-self.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'8136f9debcfa121496a265c6ce2982d5' = b64'gTb53rz6EhSWomXGzimC1Q'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed-self.ES256', L=16)
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'a1'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed-self.ES256', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50900000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a225248696843784e534e493352594d45314f7731476d3132786e726b634a5f6666707637546e2d4a71386773222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a206754623533727a36456853576f6d58477a696d433151227d'
signature = h'304402203310b9431903c401f1be2bdc8d23a4007682dbbddcf846994947b7f465daf84002204e94dd00047b316061b3b99772b7efd95994a83ef584b3b6b825ea3550251b66'
</xmp>


## ES256 Credential with "crossOrigin": true in clientDataJSON ## {#sctn-test-vectors-none-es256-crossOrigin}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'3be5aacd03537142472340ab5969f240f1d87716e20b6807ac230655fa4b3b49'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='none.ES256.crossOrigin', L=32)

credential_private_key = h'96c940e769bd9f1237c119f144fa61a4d56af0b3289685ae2bef7fb89620623d'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='none.ES256.crossOrigin', L=32)
client_data_gen_flags = h'71'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='none.ES256.crossOrigin', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'cd9aae12d0d1f435aaa56e6d0564c5ba' = b64'zZquEtDR9DWqpW5tBWTFug'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='none.ES256.crossOrigin', L=16)
aaguid = h'883f4f6014f19c09d87aa38123be48d0'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='none.ES256.crossOrigin', L=16)
credential_id = h'6e1050c0d2ca2f07c755cb2c66a74c64fa43065c18f938354d9915db2bd5ce57'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='none.ES256.crossOrigin', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'27'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='none.ES256.crossOrigin', L=1)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a224f2d57717a514e5463554a484930437257576e7951504859647862694332674872434d475666704c4f306b222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a747275652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a207a5a7175457444523944577170573574425754467567227d'
attestationObject = h'a363666d74646e6f6e656761747453746d74a068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54500000000883f4f6014f19c09d87aa38123be48d000206e1050c0d2ca2f07c755cb2c66a74c64fa43065c18f938354d9915db2bd5ce57a501020326200121582022200a473f90b11078851550d03b4e44a2279f8c4eca27b3153dedfe03e4e97d225820cbd0be95e746ad6f5a8191be11756e4c0420e72f65b466d39bc56b8b123a9c6e'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'876aa517ba83fdee65fcffdbca4c84eeae5d54f8041a1fc85c991e5bbb273137'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='none.ES256.crossOrigin', L=32)

client_data_gen_flags = h'57'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='none.ES256.crossOrigin', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'f76a5c4d50f401bcbeab876d9a3e9e7e' = b64'92pcTVD0Aby-q4dtmj6efg'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='none.ES256.crossOrigin', L=16)
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'0c'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='none.ES256.crossOrigin', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50500000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a226832716c463771445f65356c5f505f62796b7945377135645650674547685f49584a6b655737736e4d5463222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a747275652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a2039327063545644304162792d713464746d6a36656667227d'
signature = h'3046022100eb12fcf23b12764c0f122e22371fab92e283879fd798f38ee1841c951b6e40e7022100c76237ff9db77b3c56f30837cda6a09acfa2e915544e609c0733b1184036d1cf'
</xmp>


## ES256 Credential with "topOrigin" in clientDataJSON ## {#sctn-test-vectors-none-es256-topOrigin}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'4e1f4c6198699e33c14f192153f49d7e0e8e3577d5ac416c5f3adc92a41f27e5'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='none.ES256.topOrigin', L=32)

credential_private_key = h'a2d6de40ab974b80d8c1ef78c6d4300097754f7e016afe7f8ea0ad9798b0d420'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='none.ES256.topOrigin', L=32)
client_data_gen_flags = h'54'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='none.ES256.topOrigin', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
aaguid = h'97586fd09799a76401c200455099ef2a'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='none.ES256.topOrigin', L=16)
credential_id = h'b8ad59b996047ab18e2ceb57206c362da57458793481f4a8ebf101c7ca7cc0f1'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='none.ES256.topOrigin', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'a0'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='none.ES256.topOrigin', L=1)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a225468394d595a68706e6a504254786b68555f53646667364f4e58665672454673587a72636b7151664a2d55222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a747275652c22746f704f726967696e223a2268747470733a2f2f6578616d706c652e636f6d227d'
attestationObject = h'a363666d74646e6f6e656761747453746d74a068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b5410000000097586fd09799a76401c200455099ef2a0020b8ad59b996047ab18e2ceb57206c362da57458793481f4a8ebf101c7ca7cc0f1a5010203262001215820a1c47c1d82da4ebe82cd72207102b380670701993bc35398ae2e5726427fe01d22582086c1080d82987028c7f54ecb1b01185de243b359294a0ed210cd47480f0adc88'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'd54a5c8ca4b62a8e3bb321e3b2bc73856f85a10150db2939ac195739eb1ea066'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='none.ES256.topOrigin', L=32)

client_data_gen_flags = h'77'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='none.ES256.topOrigin', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'52216824c5514070c0156162e2fc54a5' = b64'UiFoJMVRQHDAFWFi4vxUpQ'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='none.ES256.topOrigin', L=16)
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'9f'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='none.ES256.topOrigin', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50500000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22315570636a4b53324b6f34377379486a7372787a68572d466f51465132796b3572426c584f6573656f4759222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a747275652c22746f704f726967696e223a2268747470733a2f2f6578616d706c652e636f6d222c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a205569466f4a4d56525148444146574669347678557051227d'
signature = h'3045022100b5a70c81780d5fcc9a4f2ae9caae99058f8accaf58b91fb59329646c28ac6ffc022012e101c165db3c8e9957f0c54dd6ca9b56bc3bd2f280bd2faa6c1d02c6e5c171'
</xmp>


## ES256 Credential with very long credential ID ## {#sctn-test-vectors-none-es256-long-credential-id}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'1113c7265ccf5e65124282fa1d7819a7a14cb8539aa4cdbec7487e5f35d8ec6c'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='none.ES256.long-credential-id', L=32)

credential_private_key = h'6fd2149bb5f1597fe549b138794bde61893b2dc32ca316de65f04808dac211dc'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='none.ES256.long-credential-id', L=32)
client_data_gen_flags = h'90'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='none.ES256.long-credential-id', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
aaguid = h'8f3360c2cd1b0ac14ffe0795c5d2638e'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='none.ES256.long-credential-id', L=16)
credential_id = h'3a761a4e1674ad6c4305869435c0eee9c286172c229bb91b48b4ada140c0863417031305cce5b4a27a88d7fe728a5f5a627de771b4b40e77f187980c124f9fe832d7136010436a056cce716680587d23187cf1fc2c62ae86fc3e508ee9617ffc74fbc10488ec16ec5e9096328669a898709b655e549738c666c1ae6281dc3b5f733c251d3eefb76ee70a3805ca91bcc18e49c8dc7f63ebcb486ba8c3d6ab52b88ff72c6a5bb47c32f3ee8683a3ddc8abf60870448ec8a21b5bdcb183c7dead870255575a6df96eb1b6a2a1019780cba9e4887b17ff1164bbbcc10eb0d86ed75984cd3fa3419103024507dfd9ce8f92c56af7914cb0bb50b87ba82a312bb7dcd93028dbdcd6adb266979667158335171e3682d37755701edbf9d872846a291d49e57ef09da1ec637f5052ed2aa7407f7e61827468e94b461844f4c67be5fa9c6055a566f8fdfc29d4bf78a9ff275f552cc68ba543fa3962eea36fd1ea8453764577d021d0a181efc1f6100ab2e4110039e21ee16970bda7432b6134492155afc126295b3a2eccd12c66a68e340969e995e3e8c9c476e395cfc21203414110779474f1c9797406637dbe414f132519d3bf0ce4f01734ef0e1a12c3ad604ff15d766b1624db6a5a7ccbff7bc35c9908df94aba277e0af48f04ff3d16381c47e5a37ed3988a67a3b1ecaa926336b33391fff04128f869991c9fabd905b6fe3ceef5f8b630ec1c5d2636d5b1961ad5ca5004170f6f5e482792aad989b0287fe91e5c479403397152f1fa56aa79b156eb47e6c8ea3eb175c34cfb38ad8e772874639b1023d4d01395c94e55831671cc022aa6fa1e02a02c2e4abc776f6960e51f83b71a8c0f207b6a347573977812c9aa5480b0011aa739bd4b76c18c000cc4757cceccb920f007c40c00e37e5ab21476cd9f6054a8fffb55a108f5c706e2cea2049d81fd321ff47d2a5761b0800955ab1d4f4889f55a84e2601c684f17a4ade7453ea49591d0b59c8d9a765052f62219cf6ef4a5dd9539f0617d6ebbebce7c000455475d18449e25c49ef9a1e3efe18c09082ebe2058d7c347defaa92f0664553b805c7d76bbfce5f330aca220ac90a789380fc479ea0d8793205813cca590a912f699ad52f991a1bc0a503c3ec4b2a696719e3c26591a87127f7305cc7e72f4c8e39355ebb06a5b1042990f38710ee7aa612ee4374bb82e878585a70a96c2a6b47f101a4ff154be4fd76a3167577a5cc54d9167c154c69ac35485e44cc898b719e1be3cc9c0fb5624b8f8a0dae10947a41bf848b6c1bb33d1006ec077d7e286e3f2a7b4843716390119449fe2721e81a5ed2333d331c7120765da58fadae73c19d9a8c4509cf8ac1e9d98b799a5274509069739b5823f3fb496663820033426988eefca53e580e0f9e0dfe0992fc2e53a97e053639f98577058f995bdbd41cefdb'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='none.ES256.long-credential-id', L=1023)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'69'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='none.ES256.long-credential-id', L=1)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22455250484a6c7a50586d5553516f4c364858675a7036464d75464f61704d322d7830682d587a5859374777222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
attestationObject = h'a363666d74646e6f6e656761747453746d74a0686175746844617461590483bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b549000000008f3360c2cd1b0ac14ffe0795c5d2638e03ff3a761a4e1674ad6c4305869435c0eee9c286172c229bb91b48b4ada140c0863417031305cce5b4a27a88d7fe728a5f5a627de771b4b40e77f187980c124f9fe832d7136010436a056cce716680587d23187cf1fc2c62ae86fc3e508ee9617ffc74fbc10488ec16ec5e9096328669a898709b655e549738c666c1ae6281dc3b5f733c251d3eefb76ee70a3805ca91bcc18e49c8dc7f63ebcb486ba8c3d6ab52b88ff72c6a5bb47c32f3ee8683a3ddc8abf60870448ec8a21b5bdcb183c7dead870255575a6df96eb1b6a2a1019780cba9e4887b17ff1164bbbcc10eb0d86ed75984cd3fa3419103024507dfd9ce8f92c56af7914cb0bb50b87ba82a312bb7dcd93028dbdcd6adb266979667158335171e3682d37755701edbf9d872846a291d49e57ef09da1ec637f5052ed2aa7407f7e61827468e94b461844f4c67be5fa9c6055a566f8fdfc29d4bf78a9ff275f552cc68ba543fa3962eea36fd1ea8453764577d021d0a181efc1f6100ab2e4110039e21ee16970bda7432b6134492155afc126295b3a2eccd12c66a68e340969e995e3e8c9c476e395cfc21203414110779474f1c9797406637dbe414f132519d3bf0ce4f01734ef0e1a12c3ad604ff15d766b1624db6a5a7ccbff7bc35c9908df94aba277e0af48f04ff3d16381c47e5a37ed3988a67a3b1ecaa926336b33391fff04128f869991c9fabd905b6fe3ceef5f8b630ec1c5d2636d5b1961ad5ca5004170f6f5e482792aad989b0287fe91e5c479403397152f1fa56aa79b156eb47e6c8ea3eb175c34cfb38ad8e772874639b1023d4d01395c94e55831671cc022aa6fa1e02a02c2e4abc776f6960e51f83b71a8c0f207b6a347573977812c9aa5480b0011aa739bd4b76c18c000cc4757cceccb920f007c40c00e37e5ab21476cd9f6054a8fffb55a108f5c706e2cea2049d81fd321ff47d2a5761b0800955ab1d4f4889f55a84e2601c684f17a4ade7453ea49591d0b59c8d9a765052f62219cf6ef4a5dd9539f0617d6ebbebce7c000455475d18449e25c49ef9a1e3efe18c09082ebe2058d7c347defaa92f0664553b805c7d76bbfce5f330aca220ac90a789380fc479ea0d8793205813cca590a912f699ad52f991a1bc0a503c3ec4b2a696719e3c26591a87127f7305cc7e72f4c8e39355ebb06a5b1042990f38710ee7aa612ee4374bb82e878585a70a96c2a6b47f101a4ff154be4fd76a3167577a5cc54d9167c154c69ac35485e44cc898b719e1be3cc9c0fb5624b8f8a0dae10947a41bf848b6c1bb33d1006ec077d7e286e3f2a7b4843716390119449fe2721e81a5ed2333d331c7120765da58fadae73c19d9a8c4509cf8ac1e9d98b799a5274509069739b5823f3fb496663820033426988eefca53e580e0f9e0dfe0992fc2e53a97e053639f98577058f995bdbd41cefdba50102032620012158203b8176b7504489cc593046d7988abb7905a742de6ac2cdc748a873c663e90cb12258201436d5edc9a75f23999eef9d5950a5c2455514ee1014084720f841a06b828a11'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'ef1deba56dce48f674a447ccf63b9599258ce87648e5c396f2ef0ca1da460e3b'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='none.ES256.long-credential-id', L=32)

client_data_gen_flags = h'80'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='none.ES256.long-credential-id', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'e5'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='none.ES256.long-credential-id', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22377833727057334f53505a307045664d396a75566d53574d36485a4935634f573875384d6f647047446a73222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
signature = h'304502203ecef83fb12a0cae7841055f9f87103a99fd14b424194bbf06c4623d3ee6e3fd022100d2ace346db262b1374a6b70faa51f518a42ddca13a4125ce6f5052a75bac9fb6'
</xmp>


## Packed Attestation with ES256 Credential ## {#sctn-test-vectors-packed-es256}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'c1184a5fddf8045e13dc47f54b61f5a656b666b59018f16d870e9256e9952012'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.ES256', L=32)

credential_private_key = h'36ed7bea2357cefa8c4ec7e134f3312d2e6ca3058519d0bcb4c1424272010432'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.ES256', L=32)
client_data_gen_flags = h'8d'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'f5af1b3588ca0a05ab05753e7c29756a' = b64'9a8bNYjKCgWrBXU-fCl1ag'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.ES256', L=16)
aaguid = h'876ca4f52071c3e9b25509ef2cdf7ed6'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.ES256', L=16)
credential_id = h'c9a6f5b3462d02873fea0c56862234f99f081728084e511bb7760201a89054a5'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.ES256', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'4f'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.ES256', L=1)
attestation_private_key = h'ec2804b222552b4b277d1f58f8c4343c0b0b0db5474eb55365c89d66a2bc96be'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.ES256', L=32)
attestation_cert_serial_number = h'88c220f83c8ef1feafe94deae45faad0'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.ES256', L=16)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a227752684b58393334424634543345663153324831706c61325a725751475046746877365356756d56494249222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20396138624e596a4b436757724258552d66436c316167227d'
attestationObject = h'a363666d74667061636b65646761747453746d74a363616c6726637369675847304502203f19ec4b229f46ab8c45eff29b904ff10c0390dc40bf1216f04a78f4ceba3425022100fe7041a32759aff05a0f9f26c70a999c7a284451ba89234a1d3483c25e21925b637835638159022530820221308201c8a00302010202110088c220f83c8ef1feafe94deae45faad0300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004a91ba4389409dd38a428141940ca8feb1ac0d7b4350558104a3777a49322f3798440f378b3398ab2d3bb7bf91322c92eb23556f59ad0a836fec4c7663b0e4dc3a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414a589ba72d060842ab11f74fb246bdedab16f9b9b301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d040302034700304402201726b9d85ecd8a5ed51163722ca3a20886fd9b242a0aa0453d442116075defd502207ef471e530ac87961a88a7f0d0c17b091ffc6b9238d30f79f635b417be5910e768617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54d00000000876ca4f52071c3e9b25509ef2cdf7ed60020c9a6f5b3462d02873fea0c56862234f99f081728084e511bb7760201a89054a5a50102032620012158201cf27f25da591208a4239c2e324f104f585525479a29edeedd830f48e77aeae522582059e4b7da6c0106e206ce390c93ab98a15a5ec3887e57f0cc2bece803b920c423'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'b1106fa46a57bef1781511c0557dc898a03413d5f0f17d244630c194c7e1adb5'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.ES256', L=32)

client_data_gen_flags = h'75'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'019330c8cc486c3f3eba0b85369eabf1' = b64'AZMwyMxIbD8-uguFNp6r8Q'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0b', info='packed.ES256', L=16)
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'46'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0c', info='packed.ES256', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273524276704770587676463446524841565833496d4b4130453958773858306b526a44426c4d6668726255222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20415a4d77794d78496244382d756775464e7036723851227d'
signature = h'30450220694969d3ee928de6f02ef23a9c644d7d779916451734a94b432542f498a1ebe90221008b0819c824218a97152cd099c55bfb1477b29d900a49a64018314f9bfccda163'
</xmp>


## Packed Attestation with ES384 Credential ## {#sctn-test-vectors-packed-es384}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'567b030b3e186bc1d169dd45b79f9e0d86f1fd63474da3eade5bdb8db379a0c3'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.ES384', L=32)

credential_private_key = h'271e37d309c558c0f35222b37abba7500377d68e179e4c74b0cb558551b2e5276b47b90a317ca8ebbe1a12c93c2d5dd9'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.ES384', L=48)
client_data_gen_flags = h'32'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.ES384', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
aaguid = h'e950dcda3bdae1d087cda380a897848b'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.ES384', L=16)
credential_id = h'953ae2dd9f28b1a1d5802c83e1f65833bb9769a08de82d812bc27c13fc6f06a9'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.ES384', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'db'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.ES384', L=1)
attestation_private_key = h'8d979fbb6e49c4eeb5925a2bca0fcdb023d3fb90bcadce8391da9da4ed2aee9a'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.ES384', L=32)
attestation_cert_serial_number = h'3d0a5588bb87ebb1d4cee4a1807c1b7c'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.ES384', L=16)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22566e7344437a3459613848526164314674352d65445962785f574e4854615071336c76626a624e356f4d4d222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
attestationObject = h'a363666d74667061636b65646761747453746d74a363616c67266373696758473045022100c56ecc970b7843833e0f461fde26233f61eb395161d481558c08b9c6ed61675b022029f5e05033705cd0f9b0a07e149468ec308a4f84906409efdceb1da20a7518d6637835638159022530820221308201c7a00302010202103d0a5588bb87ebb1d4cee4a1807c1b7c300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d0301070342000417e5cc91d676d370e36aa7de40c25aacb45a3845f13d2932088ece2270b9b431241c219c22d0c256c9438ade00f2c05e62f8ef906b9b997ae9f3c460c2db66f5a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414c7c8dd95382a2230e4c0dd3664338fa908169a9c301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020348003045022054068cc9ae038937b7c468c307edb9c6927ffdeb6a20070c483eb40330f99f10022100cf41953919c3c04693d6b1f42a613753f204e70e85fc6e9b17036170b83596e068617574684461746158c5bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55900000000e950dcda3bdae1d087cda380a897848b0020953ae2dd9f28b1a1d5802c83e1f65833bb9769a08de82d812bc27c13fc6f06a9a5010203382220022158304866bd8b01da789e9eb806e5eab05ae5a638542296ab057a2f1bbce9b58f8a08b9171390b58a37ac7fffc2c5f45857da2258302a0b024c7f4b72072a1f96bd30a7261aae9571dd39870eb29e55c0941c6b08e89629a1ea1216aa64ce57c2807bf3901a'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'ff41c3d25dbd8966fb61e28ef5e47041e137ed268520412d76202ba0ad2d1453'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.ES384', L=32)

client_data_gen_flags = h'0c'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.ES384', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'af'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed.ES384', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a225f304844306c32396957623759654b4f39655277516545333753614649454574646941726f4b307446464d222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
signature = h'3065023100e4efbb46745ed00e67c4d51ab2bacab2af62ffa8b7c5fecec6d7d9bf2582275034a713a3dd731685eee81adfaf6aa63f0230161655353f07e018a3c2539f8de7c8c4cf88d4c32d2be29fe4e76fa096ecc9458bbfe0895d57129ab324130e6f0692db'
</xmp>


## Packed Attestation with ES512 Credential ## {#sctn-test-vectors-packed-es512}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'4ee220cd92b07e11451cb4c201c5755bd879848e492a9b12d79135c62764dc2fd28ead4808cafe5ad1de8fa9e08d4a8eeafea4dfb333877b02bc503f475d3b0c1394a7683baaf4f2477829f7b8cf750948985558748c073068396fcfdcd3f245bf2038e6bb38d7532768aad13be8c118f727722e7426139041e9caca503884c5'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.ES512', L=128)

credential_private_key = h'f11120594f6a4944ac3ba59adbbc5b85016895b649f4cc949a610f4b48be47b318850bacb105f747647bba8852b6b8e52a0b3679f1bbbdfe18c99409bcb644fa45'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.ES512', L=65)
client_data_gen_flags = h'6d'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.ES512', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'a37a958ce2f6b535a6e06c64cc8fd082' = b64'o3qVjOL2tTWm4GxkzI_Qgg'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.ES512', L=16)
aaguid = h'39d8ce6a3cf61025775083a738e5c254'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.ES512', L=16)
credential_id = h'd17d5af7e3f37c56622a67c8462c9e1c6336dfccb8b61d359dc47378dba58ce4'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.ES512', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'cf'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.ES512', L=1)
attestation_private_key = h'ffbc89d5f75994f52dc5e7538ee269402d26995d40c16fb713473e34fca98be4'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.ES512', L=32)
attestation_cert_serial_number = h'8a128b7ebe52b993835779e6d9b81355'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.ES512', L=16)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22547549677a5a4b7766684646484c544341635631573968356849354a4b707353313545317869646b33435f536a713149434d722d577448656a366e676a55714f3676366b33374d7a683373437646415f5231303744424f5570326737717654795233677039376a5064516c496d465659644977484d47673562385f63305f4a46767941343572733431314d6e614b72524f2d6a424750636e636935304a684f5151656e4b796c4134684d55222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a206f3371566a4f4c327454576d3447786b7a495f516767227d'
attestationObject = h'a363666d74667061636b65646761747453746d74a363616c67266373696758473045022100ce158f6c04aa5c14c0dd3e1103cf93664896fb5c337a66dbd7dba31546ff0d41022071cbcd0d3b8e218a6d05374e0ef8031329d25059002ac1603d02d5fd8a0a29cb637835638159022730820223308201c8a0030201020211008a128b7ebe52b993835779e6d9b81355300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004940b68885291536e2f7c60c05acfb252e7eebcf4304425dd93ab7b1962f20492bf18dc0f12862599e81fb764ac92151f9a78fcbb35d7a26c8c52949b18133c06a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604143ffad863abcd3dc5717b8a252189f41af97e7f31301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020349003046022100832c8b64c4f0188bd32e1bec63e13301cdc03165d3ef840d1f3dabb9a5719f83022100add57a9d5bedec98f29222dfc97ea795d055ee13a02a153d02be9ce00aedeb9168617574684461746158e9bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54d0000000039d8ce6a3cf61025775083a738e5c2540020d17d5af7e3f37c56622a67c8462c9e1c6336dfccb8b61d359dc47378dba58ce4a5010203382320032158420083240a2c3ad21a3dc0a6daa3d8bc05a46d7cd9825ba010ae2a22686c2d6d663d7d5f678987fb1e767542e63dc197ae915e25f8ee284651af29066910a2cc083f50225842017337df47ab5cce5d716ef8caffa97a3012689b1f326ea6c43a1ba9596c72f71f0122390143552b42be772b4c35ffb961220c743b486a601ea4cb6d5412f5b078d3'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'08d3190c6dcb3d4f0cb659a0333bf5ea124ddf36a0cd33d5204b0d7a22a8cc26f2e4f169d200285c77b3fb22e0f1c7f49a87d4be2d25e92d797808ddaaa9b5715efd3a6ada9339d3052a687dbc5d2f8c871b0451e0691f57ad138541b7b72e7aa8933729ec1c664bf2e4dedae1616d08ecefa80a2a53b103663ce5a881048829'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.ES512', L=128)

client_data_gen_flags = h'ac'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed.ES512', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'52'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0b', info='packed.ES512', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22434e4d5a4447334c5055384d746c6d674d7a763136684a4e337a61677a5450564945734e65694b6f7a436279355046703067416f5848657a2d794c67386366306d6f66557669306c3653313565416a6471716d31635637394f6d72616b7a6e544253706f666278644c3479484777525234476b66563630546855473374793536714a4d334b6577635a6b7679354e376134574674434f7a7671416f71553745445a6a7a6c7149454569436b222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
signature = h'3081870242009bda02fe384e77bcb9fb42b07c395b7a53ec9d9616dd0308ab8495c2141c8364c7d16e212a4a4fb8e3987ff6c99eafd64d8484fd28c3fc7968f658a9033d1bb1b802416383e9f3ee20c691b66620299fef36bea2df4d39c92b2ead92f58e7b79ab0d9864d2ebf3b0dcc66ea13234492ccee6e9d421db43c959bcb94c162dc9494136c9f6'
</xmp>


## Packed Attestation with RS256 Credential ## {#sctn-test-vectors-packed-rs256}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'bea8f0770009bd57f2c0df6fea9f743a27e4b61bbe923c862c7aad7a9fc8e4a6'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.RS256', L=32)

; The two smallest Mersenne primes 2^p - 1 where p >= 1024
private_key_p = 2^1279 - 1 = h'7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
private_key_q = 2^2203 - 1 = h'07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
client_data_gen_flags = h'1c'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.RS256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
aaguid = h'428f8878298b9862a36ad8c7527bfef2'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.RS256', L=16)
credential_id = h'992a18acc83f67533600c1138a4b4c4bd236de13629cf025ed17cb00b00b74df'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.RS256', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'7e'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.RS256', L=1)
attestation_private_key = h'08a1322d5aa5b5b40cd67c2cc30b038e7921d7888c84c342d50d79f0c5fc3464'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.RS256', L=32)
attestation_cert_serial_number = h'1f6fb7a5ece81b45896b983a995da5f3'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.RS256', L=16)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a2276716a776477414a76566679774e3976367039304f69666b7468752d6b6a79474c48717465705f49354b59222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
attestationObject = h'a363666d74667061636b65646761747453746d74a363616c672663736967584730450221008b8c5c6ea8c142c032e0be69e1353d44461c5c9109941cdda951b976eb95b6b302204d52f406c19e254b3ff9589bd18070fb055ac8db12fdd0a6734bea9d7168e900637835638159022630820222308201c7a00302010202101f6fb7a5ece81b45896b983a995da5f3300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004b7b36b7542a11120b443c794d0c99fdc25a06b76586413d81e086163ef6fe147a557afc34e2861d9057d6d465d4705a0310550bdeeb5f35ee35b9425ab859981a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414fb37b647bccfb9e54d989eaaacc1633868703fb3301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020349003046022100b86bc129d92afca7d9869a39f70f139a305b4073a39eb654d81424bed5757d91022100cf9f7c60cab7c4a7d3e7f0020f281a93d4fd0a9f95121b989f56932a68885fba68617574684461746159021bbfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55d00000000428f8878298b9862a36ad8c7527bfef20020992a18acc83f67533600c1138a4b4c4bd236de13629cf025ed17cb00b00b74dfa4010303390100205901b403fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012143010001'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'295f59f5fa8fe62c5aca9e27626c78c8da376ae6d8cd2dd29aebad601e1bc4c5'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.RS256', L=32)

client_data_gen_flags = h'0e'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.RS256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'ba'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.RS256', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a224b56395a39667150356978617970346e596d7834794e6f33617562597a5333536d75757459423462784d55222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
signature = h'01063d52d7c39b4d432fc7063c5d93e582bdcb16889cd71f888d67d880ea730a428498d3bc8e1ee11f2b1ecbe6c292b118c55ffaaddefa8cad0a54dd137c51f1eec673f1bb6c4d1789d6826a222b22d0f585fc901fdc933212e579d199b89d672aa44891333e6a1355536025e82b25590256c3538229b55737083b2f6b9377e49e2472f11952f79fdd0da180b5ffd901b4049a8f081bb40711bef76c62aed943571f2d0575304cb549d68d8892f95086a30f93716aee818f8dc06e96c0d5e0ed4cfa9fd8773d90464b68cf140f7986666ff9c9e3302acd0535d60d769f465e2ab57ef8aabc89fccfef7ba32a64154a8b3d26be2298f470b8cc5377dbe3dfd4b0b45f8f01e63bde6cfc76b62771f9b70aa27cf40152cad93aa5acd784fd4b90f676e2ea828d0bf2400aebbaae4153e5838f537f88b6228346782a93a899be66ec77de45b3efcf311da6321c92e6b0cd11bfe653bf3e98cee8e341f02d67dbb6f9c98d9e8178090cfb5b70fbc6d541599ac794ae2f1d4de1286ec8de8c2daf7b1d15c8438e90d924df5c19045220a4c8438c1b979bbe016cf3d0eeec23c3999d4882cc645b776de930756612cdc6dd398160ff02a6'
</xmp>


## Packed Attestation with Ed25519 Credential ## {#sctn-test-vectors-packed-eddsa}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'a8abf9dabdc6b0df63466b39bda9e8a34a34e185337a59f1c579990676d3b3bd'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.EdDSA', L=32)

private_key = h'971f38c0f73aaf0c5a614eb5e26430ae1ea0ed13e4f425d96e9662349340b0b3'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.EdDSA', L=32)
client_data_gen_flags = h'bd'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.EdDSA', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'07f0d3e60ed90fffbd3932d85f922f11' = b64'B_DT5g7ZD_-9OTLYX5IvEQ'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.EdDSA', L=16)
aaguid = h'd5aa33581e8ca478e20fe713f5d32ff2'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.EdDSA', L=16)
credential_id = h'ce9f840ed96599580cd140fbc7bb3230633f50f61041aff73308ae71caa8a2bd'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.EdDSA', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'32'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.EdDSA', L=1)
attestation_private_key = h'fbe7f950684f23afd045072a8b287ad29528707c662672850ac69733ffe0db85'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.EdDSA', L=32)
attestation_cert_serial_number = h'b2cfc9ea33c8643b0e1a760463eaf164'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.EdDSA', L=16)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22714b763532723347734e396a526d733576616e6f6f306f303459557a656c6e7878586d5a426e6254733730222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20425f44543567375a445f2d394f544c59583549764551227d'
attestationObject = h'a363666d74667061636b65646761747453746d74a363616c67266373696758483046022100d83f60bd80269537583218858aefb03ac57d45fa06e42feaae332d187f62da9f022100a02bd3cb6f7e1d283c93bad1f3f4b5a4c0494463da7fdbf256949116754d1f17637835638159022730820223308201c8a003020102021100b2cfc9ea33c8643b0e1a760463eaf164300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004dd2b7a564b73b8c0b81c4c62e521925c4d1198ec9f583dbf1eebe364b65cd9c29a9bdf346aaa81fb6b9507e5249a52fdaf8e39e26b0b7dc45992a7e233b70f70a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604140ae27546bc7eccb1b4b597bd354f0c0b1f1f8f8e301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020349003046022100a0d434ecb5fc3bfd7da5f41904517ad2836249f561bd834ba7a438a8ab7a4ce8022100fac845bb7a02513b58e9f319654dbe49b0f02b95835bac568c71f8a18cdde9ab6861757468446174615881bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54100000000d5aa33581e8ca478e20fe713f5d32ff20020ce9f840ed96599580cd140fbc7bb3230633f50f61041aff73308ae71caa8a2bda401010327200621582044e06ddd331c36a8dc667bab52bcae63486c916aa5e339e6acebaa84934bf832'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'895957e01c633a698348a2d8a31a54b7db27e8c1c43b2080d79ae2190267bfd2'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.EdDSA', L=32)

client_data_gen_flags = h'8c'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed.EdDSA', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'ab'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0b', info='packed.EdDSA', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50100000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2269566c583442786a4f6d6d44534b4c596f7870557439736e364d48454f7943413135726947514a6e763949222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
signature = h'f5c59c7e46c34f6f8cc197101ddf9934fa2595f68eb1913a637e8419eb9ba4cfdfc48f85393bc0d40b011f0d6fecb097d6607525713223a0dc0d453993dae00b'
</xmp>


## Packed Attestation with Ed448 Credential ## {#sctn-test-vectors-packed-ed448}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'2578d0801b5a005b5451e540121788cb01949e187b91db13f58755403efbf337'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.Ed448', L=32)

private_key = h'ed479eecf63bd89e3898434798bb3c417bfc8284f6f011958bc0e78edbf6a2a640c0e358b1b1452a1f3782c400dabb4134192dee3031869a45'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.Ed448', L=57)
client_data_gen_flags = h'e3'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.Ed448', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'050a80de27875521cc4c3316c06da42b' = b64'BQqA3ieHVSHMTDMWwG2kKw'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.Ed448', L=16)
aaguid = h'41c913aeda925fe02273322e34c2ae67'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.Ed448', L=16)
credential_id = h'224fcde324e6b075ede55098a24b9ddce5f5a7c71d23703efd528a38f8a5f33c'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.Ed448', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'3b'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.Ed448', L=1)
attestation_private_key = h'd90faf5cc3f7853456b09124dd870250347f9c9ff66dba363aecd9194c665715'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.Ed448', L=32)
attestation_cert_serial_number = h'cff4228697d6e5ac47480b2390677f05'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.Ed448', L=16)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a224a586a5167427461414674555565564145686549797747556e6868376b6473543959645651443737387a63222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a2042517141336965485653484d54444d577747326b4b77227d'
attestationObject = h'a363666d74667061636b65646761747453746d74a363616c67266373696758473045022100c5430b6b53f6b8fd1e5fa46ae7ebb8f9e9ae0d10ebc748e876e2d979b39b1382022008c5cda8af174f2d3c050d5d14eec0721031364cb12924a06633d4924c6bcad3637835638159022730820223308201c8a003020102021100cff4228697d6e5ac47480b2390677f05300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004b85aaf790c824037cfe9fc56ab8d7ce6fbfaff2e3fe7c8d745734c3c6e3c6ce880d505ccdb1e2c3738680e6f49f475e4d8d0b6c29060e6e0d7a6392fb69094cea360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414fa8f81c2dcc0e194ae5034c7e79dcf6d9d8593e2301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020349003046022100e761f54215ad92f27c2c14b9eea3e39e8c22429e833ecba5be918987aa72e0e6022100d5a714df479c238586b7d9e6684ea84991087038b0fef6a29b57b66b74df05fd686175746844617461589bbfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b5590000000041c913aeda925fe02273322e34c2ae670020224fcde324e6b075ede55098a24b9ddce5f5a7c71d23703efd528a38f8a5f33ca4010103383420072158398051ef4f94670b5abf17da2e9558ba6eba94eb8704363915b4d666de287ad329de9f1f075211aba602dc6e7a5e52b15a8ee1c984a9f8887380'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'1a942f401d8d8e36fe888c35c22b718217802fc6685bf139c47b311408128693'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.Ed448', L=32)

client_data_gen_flags = h'2d'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed.Ed448', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'5ca1e381b5e009e01760db2eb632316f' = b64'XKHjgbXgCeAXYNsutjIxbw'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0b', info='packed.Ed448', L=16)
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'fc'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0c', info='packed.Ed448', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51d00000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22477051765142324e6a6a622d6949773177697478676865414c385a6f575f4535784873784641675368704d222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20584b486a6762586743654158594e7375746a49786277227d'
signature = h'071db921430e13ca1a607eedb96cbd30fd63946a06e731217cad6fd82ba3b930d482308a2c101752a2518cff70918d4a20f29bd2eda4f45a80bba6c4ad85b10fb721b1849725b7dbef315d5fb101c6dab890b06d94a8b52a74b5848f68e6152af24867b7555d2b22b8955cbff5c87de73b00'
</xmp>


## TPM Attestation with ES256 Credential ## {#sctn-test-vectors-tpm-es256}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'cfc82cdf1ceee876120aa88f0364f0910193460cfb97a317b2fe090694f9a299'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='tpm.ES256', L=32)

credential_private_key = h'80c60805e564f6d33e7abdff9d32e3db09a6219fe378a268d23107191b18e39f'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='tpm.ES256', L=32)
client_data_gen_flags = h'84'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='tpm.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
aaguid = h'4b92a377fc5f6107c4c85c190adbfd99'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='tpm.ES256', L=16)
credential_id = h'ec27bec7521c894bbb821105ea3724c90e770cf1fa354157ef18d0f18f78bea9'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='tpm.ES256', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'af'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='tpm.ES256', L=1)
attestation_private_key = h'6210f09e0ce7593e851a880a4bdde2d2192afeac46104abce1a890a5a71cf0c6'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='tpm.ES256', L=32)
attestation_cert_serial_number = h'311fc42da0ab10c43a9b1bf3a75e34e2'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='tpm.ES256', L=16)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a227a38677333787a753648595343716950413254776b51475452677a376c364d587376344a427054356f706b222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
attestationObject = h'a363666d746374706d6761747453746d74a663616c67266373696758463044022066e5826a652091030fd444e33c3eca2bc6dc548cf3045013addb38aa6457a21002203f3a5c95c9e707d0e555041bcc8698ee4ebc04e26cc8bae459705471789851766376657263322e30637835638159023a30820236308201dca0030201020210311fc42da0ab10c43a9b1bf3a75e34e2300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d03010703420004c54e3f109094f60d7699b7db5d838569ffd1f3e1c9e897cd9eb40063f9402e3e9937e936cf1fcd5eb743ff443c97ab2edcd7c8e0e6cf6cfd413b8ab19fffa769a381d33081d0300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604145f546cb6973d4981e80fcdc7463859f5879680e4301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e30100603551d250409300706056781050803305e0603551d110101ff04543052a450304e314c3014060567810502010c0b69643a30303030303030303014060567810502030c0b69643a3030303030303030301e060567810502020c15576562417574686e207465737420766563746f7273300a06082a8648ce3d0403020348003045022063c9a2797b8066f1db34dd609f1ab6695607e7a98e9ff8090a68853c9a9fc949022100a55831a39f5b8a2aa9a68837829cabf43fea2a5cea4859ae851cac78e6ac3e97677075624172656158560023000b0004000000000010001000030010002041202698c9d9753fb4bb3f27cd09fe6b8afdb76438ee2ae54d7c9dade10d864b0020d8735115cdb330a63ea1d6e43d5000f4bd56f99bce83ee1d73301fc270116d076863657274496e666f5869ff544347801700000020277d0e05579dd013215a62273f7f3a3e7e191ead2654a3036d75a5a3ee37a6b0000000000000000011111111222222223300000000000000000022000b9c42d8aad5939331b9af3711af179f17123178098c9a7d0ca89fcd1fc800f3c7000068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54d000000004b92a377fc5f6107c4c85c190adbfd990020ec27bec7521c894bbb821105ea3724c90e770cf1fa354157ef18d0f18f78bea9a501020326200121582041202698c9d9753fb4bb3f27cd09fe6b8afdb76438ee2ae54d7c9dade10d864b225820d8735115cdb330a63ea1d6e43d5000f4bd56f99bce83ee1d73301fc270116d07'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'00093b66c21d5b5e89f7a07082118907ea3e502d343b314b8c5a54d62db202fb'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='tpm.ES256', L=32)

client_data_gen_flags = h'86'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='tpm.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'87'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='tpm.ES256', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2241416b375a7349645731364a393642776768474a422d6f2d554330304f7a464c6a46705531693279417673222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
signature = h'3045022060dc76b1607ec716c6e5eba8d056695ed6bc47b2e3d7a729c34e759e3ab66aa0022100d010a9e8fddcb64c439dfdca628ddb33cf245d567d157d9f66f942601bed9b38'
</xmp>


## Android Key Attestation with ES256 Credential ## {#sctn-test-vectors-android-key-es256}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'3de1f0b7365dccde3ff0cbf25e26ffa7baff87ef106c80fc865dc402d9960050'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='android-key.ES256', L=32)

credential_private_key = h'd4328d911acb0ebcc42aad29b29ffb55d5bc31d8af7ca9a16703d56c21abc7b4'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='android-key.ES256', L=32)
client_data_gen_flags = h'73'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='android-key.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'555d5c42e476a8b33f6a63dfa07ccbd2' = b64'VV1cQuR2qLM_amPfoHzL0g'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='android-key.ES256', L=16)
aaguid = h'ade9705e1ce7085b899a540d02199bf8'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='android-key.ES256', L=16)
credential_id = h'0a4729519788b6ed8a2d772b494e186244d8c798c052960dbc8c10c915176795'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='android-key.ES256', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'1e'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='android-key.ES256', L=1)
attestation_cert_serial_number = h'1ff91f76b63f44812f998b250b0286bf'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='android-key.ES256', L=16)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a2250654877747a5a647a4e345f384d76795869625f7037725f682d385162494438686c334541746d57414641222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a205656316351755232714c4d5f616d50666f487a4c3067227d'
attestationObject = h'a363666d746b616e64726f69642d6b65796761747453746d74a363616c67266373696758483046022100e95512982aa3f216cff2e87c8ec57057b8529f674eaabeccaa27fd03d8779f19022100afb6bf459da4a826f00d01fc6b60712ff31dc4eb331619c8f874bb17e4314e94637835638159026f3082026b30820210a00302010202101ff91f76b63f44812f998b250b0286bf300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d0301070342000499169657036d089a2a9821a7d0063d341f1a4613389359636efab5f3cbf1accfdd91c55543176ea99b644406dd1dd63774b6af65ac759e06ff40b1c8ab02df6ba381a83081a5300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604141ac81e50641e8d1339ab9f7eb25f0cd5aac054b0301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e3045060a2b06010401d679020111043730350202012c0201000201000201000420b435028d7b6a8f83bb461d41c19b053a9d3cdb30351a4f374cd4cde8dbefb606040030003000300a06082a8648ce3d040302034900304602210081671f2474f336e6b5a868d28b47cd054c0ed4261f531fcdf1a1ceed19f600ad022100e7ac683848c34842a432ff4a26e9dbc537b88e83fc4cb59138de3ca3a3e1081468617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55d00000000ade9705e1ce7085b899a540d02199bf800200a4729519788b6ed8a2d772b494e186244d8c798c052960dbc8c10c915176795a501020326200121582099169657036d089a2a9821a7d0063d341f1a4613389359636efab5f3cbf1accf225820dd91c55543176ea99b644406dd1dd63774b6af65ac759e06ff40b1c8ab02df6b'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'e4ee05ca9dbced74116540f24ed9adc62aae8507560522844ffa7eea14f7af86'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='android-key.ES256', L=32)

client_data_gen_flags = h'43'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='android-key.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'ab127107eff182bc3230beb5f1dad29c' = b64'qxJxB-_xgrwyML618drSnA'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='android-key.ES256', L=16)
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'4a'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0b', info='android-key.ES256', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50900000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22354f344679703238375851525a55447954746d74786971756851645742534b45545f702d36685433723459222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a2071784a78422d5f78677277794d4c3631386472536e41227d'
signature = h'3045022100a2b5e37da43ceb63566f6e2817c6cbef261073d0cadfd213ff6229bd33ddea6c02203d77eb3202fc92b9b5bb843ef082c7766f8c7f23194c92708ff2f3d1de765a8f'
</xmp>


## Apple Anonymous Attestation with ES256 Credential ## {#sctn-test-vectors-apple-es256}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'f7f688213852007775009cf8c096fda89d60b9a9fb5a50dd81dd9898af5a0609'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='apple.ES256', L=32)

credential_private_key = h'de987bd9d43eeb44728ce0b14df11209dff931fb56b5b1948de4c0da1144ded0'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='apple.ES256', L=32)
client_data_gen_flags = h'5f'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='apple.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
extraData_random = h'4e32cf9e939a5d052b14d71b1f6b5364' = b64'TjLPnpOaXQUrFNcbH2tTZA'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='apple.ES256', L=16)
aaguid = h'748210a20076616a733b2114336fc384'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='apple.ES256', L=16)
credential_id = h'9c4a5886af9283d9be3e9ec55978dedfdce2e3b365cab193ae850c16238fafb8'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='apple.ES256', L=32)
; auth_data_UV_BE_BS determines the UV, BE and BS bits of the authenticator data flags, but BS is set only if BE is
auth_data_UV_BE_BS = h'2a'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='apple.ES256', L=1)
attestation_cert_serial_number = h'394275613d5310b81a29ce90f48b61c1'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='apple.ES256', L=16)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22395f61494954685341486431414a7a34774a6239714a316775616e37576c4464676432596d4b396142676b222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20546a4c506e704f6158515572464e6362483274545a41227d'
attestationObject = h'a363666d74656170706c656761747453746d74a1637835638159025c30820258308201fea0030201020210394275613d5310b81a29ce90f48b61c1300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d030107034200048a3d5b1b4c543a706bf6e4b00afedb3c930b690dd286934fe2911f779cc7761af728e1aa3b0ff66692192daa776b83ddf8e3340d2d9a0eabdfc324eb3e2f136ca38196308193300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e0416041412f1ce6c0ae39b403bfc9200317bc183a4e4d766301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e303306092a864886f76364080204263024a1220420d7a86e7233fb843eb0eeb407d8b76ff7e4f82d218cf5dbb461d752073f5cb29a300a06082a8648ce3d0403020348003045022070f5c2ede3000e9dae358d412b26a4acbf18f4cdeb80f5b13fcd564d090c39ec022100f672e2c3dbe117c9b1490b3c660abf5dcd74398187082dacb58b6744de4aca6068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54900000000748210a20076616a733b2114336fc38400209c4a5886af9283d9be3e9ec55978dedfdce2e3b365cab193ae850c16238fafb8a50102032620012158208a3d5b1b4c543a706bf6e4b00afedb3c930b690dd286934fe2911f779cc7761a225820f728e1aa3b0ff66692192daa776b83ddf8e3340d2d9a0eabdfc324eb3e2f136c'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'd3eb2964641e26fed023403a72dde093b19c4ba9008c3f9dd83fcfd347a66d05'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='apple.ES256', L=32)

client_data_gen_flags = h'c2'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='apple.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'e2'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='apple.ES256', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50900000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22302d73705a4751654a76375149304136637433676b37476353366b416a442d6432445f503030656d625155222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
signature = h'3046022100ee35db795ce28044e1f8231d68b3d79a9882f7415aa35c1b5ac74d24251073c8022100dcc65691650a412d0ceef843710c09827acf26c7845bddac07eec95863e7fc4c'
</xmp>


## FIDO U2F Attestation with ES256 Credential ## {#sctn-test-vectors-fido-u2f-es256}

[=registration ceremony|Registration=]:
<xmp class="example" highlight="cddl">
challenge = h'e074372990b9caa507a227dfc67b003780c45325380d1a90c20f81ed7d080c06'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='fido-u2f.ES256', L=32)

credential_private_key = h'51bd002938fa10b83683ac2a2032d0a7338c7f65a90228cfd1f61b81ec7288d0'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='fido-u2f.ES256', L=32)
client_data_gen_flags = h'00'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='fido-u2f.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
aaguid = h'afb3c2efc054df425013d5c88e79c3c1'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='fido-u2f.ES256', L=16)
credential_id = h'a4ba6e2d2cfec43648d7d25c5ed5659bc18f2b781538527ebd492de03256bdf4'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='fido-u2f.ES256', L=32)
attestation_private_key = h'66fda477a2a99d14c5edd7c1041a297ba5f3375108b1d032b79429f42349ce33'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='fido-u2f.ES256', L=32)
attestation_cert_serial_number = h'04f66dc6542ea7719dea416d325a2401'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='fido-u2f.ES256', L=16)

clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22344851334b5a4335797155486f696666786e73414e344445557955344452715177672d4237583049444159222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
attestationObject = h'a363666d74686669646f2d7532666761747453746d74a26373696758473045022100f41887a20063bb26867cb9751978accea5b81791a68f4f4dd6ea1fb6a5c086c302204e5e00aa3895777e6608f1f375f95450045da3da57a0e4fd451df35a31d2d98a637835638159022530820221308201c7a003020102021004f66dc6542ea7719dea416d325a2401300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d0301070342000456fffa7093dede46aefeefb6e520c7ccc78967636e2f92582ba71455f64e93932dff3be4e0d4ef68e3e3b73aa087e26a0a0a30b02dc2aa2309db4c3a2fc936dea360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414420822eb1908b5cd3911017fbcad4641c05e05a3301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d040302034800304502200d0b777f0a0b181ad2830275acc3150fd6092430bcd034fd77beb7bdf8c2d546022100d4864edd95daa3927080855df199f1717299b24a5eecefbd017455a9b934d8f668617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54100000000afb3c2efc054df425013d5c88e79c3c10020a4ba6e2d2cfec43648d7d25c5ed5659bc18f2b781538527ebd492de03256bdf4a5010203262001215820b0d62de6b30f86f0bac7a9016951391c2e31849e2e64661cbd2b13cd7d5508ad225820503b0bda2a357a9a4b34475a28e65b660b4898a9e3e9bbf0820d43494297edd0'
</xmp>

[=authentication ceremony|Authentication=]:
<xmp class="example" highlight="cddl">
challenge = h'f90c612981d84f599438de1a500f76926e92cc84bef8e02c6e23553f00485435'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='fido-u2f.ES256', L=32)

client_data_gen_flags = h'2c'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='fido-u2f.ES256', L=1)
; extraData is added to clientDataJSON iff bit 0x01 of client_data_gen_flags is 1
; auth_data_UV_BS sets the UV and BS bits of the authenticator data flags, but BS is set only if BE was set in the registration
auth_data_UV_BS = h'd1'   ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='fido-u2f.ES256', L=1)

authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50100000000'
clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a222d5178684b59485954316d554f4e3461554139326b6d36537a49532d2d4f417362694e5650774249564455222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d'
signature = h'304402206172459958fea907b7292b92f555034bfd884895f287a76200c1ba287239137002204727b166147e26a21bbc2921d192ebfed569b79438538e5c128b5e28e6926dd7'
</xmp>
<!-- END GENERATED CONTENT: Use test-vectors/webauthn-test-vectors.py -->


## Test Vectors for [=WebAuthn Extensions=] ## {#test-vectors-extensions}

This section lists example values for [=WebAuthn extensions=].


### Pseudo-random function extension (prf) ### {#test-vectors-extensions-prf}

This section lists example values for the pseudo-random function ([=prf=]) extension.

Because the [=prf=] extension integrates with the CTAP2 `hmac-secret` extension [[FIDO-CTAP]],
the examples are divided into two sections:
example inputs and outputs for the WebAuthn [=prf=] extension, relevant to [=[WACS]=] and [=[WRPS]=];
and example mappings between the WebAuthn [=prf=] extension and the CTAP2 `hmac-secret` extension,
relevant to [=[WACS]=] and [=[WAAS]=].


#### Web Authentication API #### {#test-vectors-extensions-prf-webauthn}

The following examples may be used to test [=[WAC]=] implementations of and [=[WRP]=] usage of the [=prf=] extension.
The examples are not exhaustive.

- The {{AuthenticationExtensionsPRFOutputs/enabled}} output is always present during [=registration ceremonies=],
    and never present during [=authentication ceremonies=]:

    <xmp class="example" highlight="js">
    // Example extension inputs:
    { prf: {} }

    // Example client extension outputs from navigator.credentials.create():
    { prf: { enabled: true } }
    { prf: { enabled: false } }

    // Example client extension outputs from navigator.credentials.get():
    { prf: {} }
    </xmp>

- The {{AuthenticationExtensionsPRFOutputs/results}} output may be present
    during [=registration ceremonies=] or [=authentication ceremonies=]
    if the {{AuthenticationExtensionsPRFInputs/eval}} or {{AuthenticationExtensionsPRFInputs/evalByCredential}} input is present:

    <xmp class="example" highlight="js">
    // Example extension inputs:
    { prf: { eval: { first: new Uint8Array([1, 2, 3, 4]) } } }

    // Example client extension outputs from navigator.credentials.create():
    { prf: { enabled: true } }
    { prf: { enabled: false } }
    { prf: { enabled: true, results: { first: ArrayBuffer } } }

    // Example client extension outputs from navigator.credentials.get():
    { prf: {} }
    { prf: { results: { first: ArrayBuffer } } }
    </xmp>

- The <code>{{AuthenticationExtensionsPRFOutputs/results}}.{{AuthenticationExtensionsPRFValues/second}}</code> output
    is present if and only if the {{AuthenticationExtensionsPRFOutputs/results}} output is present
    and the <code>{{AuthenticationExtensionsPRFValues/second}}</code> input was present in the chosen PRF inputs:

    <xmp class="example" highlight="js">
    // Example extension inputs:
    {
      prf: {
        eval: {
          first: new Uint8Array([1, 2, 3, 4]),
          second: new Uint8Array([5, 6, 7, 8]),
        },
        evalByCredential: {
          "e02eZ9lPp0UdkF4vGRO4-NxlhWBkL1FCmsmb1tTfRyE": {
            first: new Uint8Array([9, 10, 11, 12]),
          }
        }
      }
    }

    // Example client extension outputs from navigator.credentials.get() if credential "e02eZ9lP..." was used:
    { prf: { results: { first: ArrayBuffer } } }

    // Example client extension outputs from navigator.credentials.get() if a different credential was used:
    { prf: {} }
    { prf: { results: { first: ArrayBuffer, second: ArrayBuffer } } }
    </xmp>

- The {{AuthenticationExtensionsPRFValues/first}} and {{AuthenticationExtensionsPRFValues/second}} outputs
    may be any {{BufferSource}} type.
    Equal {{AuthenticationExtensionsPRFValues/first}} and {{AuthenticationExtensionsPRFValues/second}} inputs
    result in equal {{AuthenticationExtensionsPRFValues/first}} and {{AuthenticationExtensionsPRFValues/second}} outputs:

    <xmp class="example" highlight="js">
    // Example extension inputs:
    {
      prf: {
        evalByCredential: {
          "e02eZ9lPp0UdkF4vGRO4-NxlhWBkL1FCmsmb1tTfRyE": {
            first: new Uint8Array([9, 10, 11, 12]),
            second: new Uint8Array([9, 10, 11, 12])
          }
        }
      }
    }

    // Example client extension outputs from navigator.credentials.get():
    {
      prf: {
        results: {
          first: new Uint8Array([0xc4, 0x17, 0x2e, 0x98, 0x2e, 0x90, 0x97, 0xc3, 0x9a, 0x6c, 0x0c, 0xb7, 0x20, 0xcb, 0x37, 0x5b, 0x92, 0xe3, 0xfc, 0xad, 0x15, 0x4a, 0x63, 0xe4, 0x3a, 0x93, 0xf1, 0x09, 0x6b, 0x1e, 0x19, 0x73]),
          second: new Uint32Array([0x982e17c4, 0xc397902e, 0xb70c6c9a, 0x5b37cb20, 0xadfce392, 0xe4634a15, 0x09f1933a, 0x73191e6b]),
        }
      }
    }
    </xmp>

Pseudo-random values used in this section were generated as follows:

- <code>"e02eZ9lPp0UdkF4vGRO4-NxlhWBkL1FCmsmb1tTfRyE" = Base64Url(SHA-256(UTF-8("WebAuthn PRF test vectors") || 0x00))</code>
- <code>h&apos;c4172e982e9097c39a6c0cb720cb375b92e3fcad154a63e43a93f1096b1e1973' = SHA-256(UTF-8("WebAuthn PRF test vectors") || 0x01)</code>


<!-- GENERATED CONTENT: Use test-vectors/webauthn-prf-test-vectors.py -->
#### CTAP2 `hmac-secret` extension #### {#test-vectors-extensions-prf-ctap}

The following examples may be used to test [=[WAC]=] implementations
of how the [=prf=] extension uses the [[FIDO-CTAP]] `hmac-secret` extension.
The examples are given in CDDL [[RFC8610]] notation.
The examples are not exhaustive.

- The following shared definitions are used in all subsequent examples:

    <xmp class="example" highlight="cddl">
    ; Given input parameters:
    platform_key_agreement_private_key = 0x0971bc7fb1be48270adcd3d9a5fc15d5fb0f335b3071ff36a54c007fa6c76514
    authenticator_key_agreement_public_key = {
        1: 2,
        3: -25,
        -1: 1,
        -2: h'a30522c2de402b561965c3cf949a1cab020c6f6ea36fcf7e911ac1a0f1515300',
        -3: h'9961a929abdb2f42e6566771887d41484d889e735e3248518a53112d2b915f00',
    }
    authenticator_cred_random = h'437e065e723a98b2f08f39d8baf7c53ecb3c363c5e5104bdaaf5d5ca2e028154'
    </xmp>

    The {{AuthenticationExtensionsPRFValues/first}} and {{AuthenticationExtensionsPRFValues/second}} inputs
    are mapped in the examples as `prf_eval_first` and `prf_eval_second`, respectively.
    The `prf_results_first` and `prf_results_second` values in the examples
    are mapped to the
    <code>{{AuthenticationExtensionsPRFOutputs/results}}.{{AuthenticationExtensionsPRFValues/first}}</code>
    and <code>{{AuthenticationExtensionsPRFOutputs/results}}.{{AuthenticationExtensionsPRFValues/second}}</code>
    outputs, respectively.

- Single input case using PIN protocol 2:

    <xmp class="example" highlight="cddl">
    ; Inputs from Relying Party:
    prf_eval_first = h'576562417574686e20505246207465737420766563746f727302'

    ; Client computes:
    shared_secret = h'0c63083de8170101d38bcf8bd72309568ddb4550867e23404b35d85712f7c20d8bc911ee23c06034cbc14290b9669bec07739053c5a416e313ef905c79955876'
    salt1 = h'527413ebb48293772df30f031c5ac4650c7de14bf9498671ae163447b6a772b3'
    salt_enc = h'23dde5e3462daf36559b85c4ac5f9656aa9bfd81c1dc2bf8533c8b9f3882854786b4f500e25b4e3d81f7fc7c74236229'

    ; Authenticator computes:
    output1 = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
    output_enc = h'3bfaa48f7952330d63e35ff8cd5bca48d2a12823828915749287256ab146272f9fb437bf65691243c3f504bd7ea6d5e6'

    ; Client decrypts:
    prf_results_first = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
    </xmp>

- Two input case using PIN protocol 2:

    <xmp class="example" highlight="cddl">
    ; Inputs from Relying Party:
    prf_eval_first = h'576562417574686e20505246207465737420766563746f727302'
    prf_eval_second = h'576562417574686e20505246207465737420766563746f727303'

    ; Client computes:
    shared_secret = h'0c63083de8170101d38bcf8bd72309568ddb4550867e23404b35d85712f7c20d8bc911ee23c06034cbc14290b9669bec07739053c5a416e313ef905c79955876'
    salt1 = h'527413ebb48293772df30f031c5ac4650c7de14bf9498671ae163447b6a772b3'
    salt2 = h'd68ac03329a10ee5e0ec834492bb9a96a0e547baf563bf78ccbe8789b22e776b'
    salt_enc = h'd9f4236403e0fe843a8e4e5be764d120904c198ad6e77b089876a3391961f183b0008b4ca66b91cd72aa35b6151ff981f6e5649f3c040e6615ad7dd8ae96ef23b229a5c97c3f0dcd8605eee166ce163a'

    ; Authenticator computes:
    output1 = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
    output2 = h'a62a8773b19cda90d7ed4ef72a80a804320dbd3997e2f663805ad1fd3293d50b'
    output_enc = h'90ee52f739043bc17b3488a74306d7801debb5b61f18662c648a25b5b5678ede482cdaff99a537a44f064fcb10ce6e04dfd27619dc96a0daff8507e499296b1eecf0981f7c8518b277a7a3018f5ec6fb'

    ; Client decrypts:
    prf_results_first = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
    prf_results_second = h'a62a8773b19cda90d7ed4ef72a80a804320dbd3997e2f663805ad1fd3293d50b'
    </xmp>

- Single input case using PIN protocol 1:

    <xmp class="example" highlight="cddl">
    ; Inputs from Relying Party:
    prf_eval_first = h'576562417574686e20505246207465737420766563746f727302'

    ; Client computes:
    shared_secret = h'23e5ed7157c25892b77732fb9c8a107e3518800db2af4142f9f4adfacb771d39'
    salt1 = h'527413ebb48293772df30f031c5ac4650c7de14bf9498671ae163447b6a772b3'
    salt_enc = h'ab8c878bb05d04700f077ed91845ec9c503c925cb12b327ddbeb4243c397f913'

    ; Authenticator computes:
    output1 = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
    output_enc = h'15d4e4f3f04109b492b575c1b38c28585b6719cf8d61304215108d939f37ccfb'

    ; Client decrypts:
    prf_results_first = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
    </xmp>

Inputs and pseudo-random values used in this section were generated as follows:

- <code>seed = UTF-8("WebAuthn PRF test vectors")</code>
- <code>prf_eval_first = seed || 0x02</code>
- <code>prf_eval_second = seed || 0x03</code>
- <code>platform_key_agreement_private_key = SHA-256(seed || 0x04)</code>
- <code>authenticator_key_agreement_public_key = P256-Public-Key(sk)</code>
    where <code>sk = SHA-256(seed || 0x05)</code>
- <code>authenticator_cred_random = SHA-256(seed || 0x06)</code>
- `iv` in single-input `salt_enc` with PIN protocol 2: Truncated <code>SHA-256(seed || 0x07)</code>
- `iv` in two-input `salt_enc` with PIN protocol 2: Truncated <code>SHA-256(seed || 0x08)</code>
- `iv` in single-input `output_enc` with PIN protocol 2: Truncated <code>SHA-256(seed || 0x09)</code>
- `iv` in two-input `output_enc` with PIN protocol 2: Truncated <code>SHA-256(seed || 0x0a)</code>
<!-- END GENERATED CONTENT: Use test-vectors/webauthn-prf-test-vectors.py -->


# Acknowledgements # {#sctn-acknowledgements}
We thank the following people for their reviews of, and contributions to, this specification:
Yuriy Ackermann,
James Barclay,
Richard Barnes,
Dominic Battré,
Julien Cayzac,
Domenic Denicola,
Rahul Ghosh,
Brad Hill,
Nidhi Jaju,
Jing Jin,
Wally Jones,
Ian Kilpatrick,
Axel Nennker,
Zack Newman,
Yoshikazu Nojima,
Kimberly Paulhamus,
Adam Powers,
Yaron Sheffer,
Anne van Kesteren,
Johan Verrept,
and
Boris Zbarsky.

Thanks to Adam Powers for creating the overall [=registration=] and [=authentication=] flow diagrams
([Figure 1](#fig-registration) and [Figure 2](#fig-authentication)).

We thank
Anthony Nadalin,
John Fontana,
and
Richard Barnes
for their contributions as co-chairs of the <a href="https://www.w3.org/Webauthn/">Web Authentication Working Group</a>.

We also thank
Simone Onofri,
Philippe Le Hégaret,
Wendy Seltzer,
Samuel Weiler,
and
Harry Halpin
for their contributions as our W3C Team Contacts.


# Revision History # {#revision-history}

[INFORMATIVE]

This section summarizes the significant changes that have been made to this specification over time.

## Changes since Web Authentication Level 2 [[webauthn-2-20210408]] ## {#changes-since-l2}

### Substantive Changes ### {#changes-l3-substantive}

The following changes were made to the [=Web Authentication API=] and the way it operates.

Changes:

- Updated timeout guidance: [[#sctn-timeout-recommended-range]]
- `uvm` extension no longer included; see instead L2 [[webauthn-2-20210408]].
- [=authData/attestedCredentialData/aaguid=] in [=attested credential data=] is no longer zeroed
    when {{PublicKeyCredentialCreationOptions/attestation}} preference is {{AttestationConveyancePreference/none}}: [[#sctn-createCredential]]
- Added requirement for ESP256 (-9), ESP384 (-51) and ESP512 (-52) public keys to use uncompressed form: [[#sctn-alg-identifier]]


Deprecations:

- Registration parameter
    <code>{{CredentialCreationOptions/publicKey}}.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialEntity/name}}</code>:
    [[#dictionary-pkcredentialentity]]
- [[#sctn-android-safetynet-attestation]]
- [=CollectedClientData/tokenBinding=] was changed to \[RESERVED].
- In-field language and direction metadata are no longer recommended:
      - [[#sctn-strings-langdir]]
      - <code>{{CredentialCreationOptions/publicKey}}.{{PublicKeyCredentialCreationOptions/rp}}.{{PublicKeyCredentialEntity/name}}</code>
      - <code>{{CredentialCreationOptions/publicKey}}.{{PublicKeyCredentialCreationOptions/user}}.{{PublicKeyCredentialEntity/name}}</code>
      - <code>{{CredentialCreationOptions/publicKey}}.{{PublicKeyCredentialCreationOptions/user}}.{{PublicKeyCredentialUserEntity/displayName}}</code>
- Added recommendation against using {{COSEAlgorithmIdentifier}} values -9, -51, -52 and -19
    in {{PublicKeyCredentialCreationOptions/pubKeyCredParams}}.


New features:

- New JSON (de)serialization methods:
    - {{PublicKeyCredential/toJSON()}} method in [[#iface-pkcredential]]
    - [[#sctn-parseCreationOptionsFromJSON]]
    - [[#sctn-parseRequestOptionsFromJSON]]
- Create operations in cross-origin iframes:
    - [[#sctn-createCredential]]
    - [[#sctn-iframe-guidance]]
- Conditional mediation for create: [[#sctn-createCredential]]
- Conditional mediation for get: [[#sctn-getAssertion]]
- [[#sctn-getClientCapabilities]]
    - [[#sctn-disclosing-client-capabilities]]
- New enum value {{AuthenticatorTransport/hybrid}} in [[#enum-transport]].
- [[#sctn-signal-methods]]
- New [=client data=] attribute {{CollectedClientData/topOrigin}}: [[#dictionary-client-data]]
- [[#enum-hints]]
- [[#sctn-related-origins]]
- [=Authenticator data=] flags [=authData/flags/BE=] and [=authData/flags/BS=] assigned:
    - [[#sctn-authenticator-data]]
    - [[#sctn-credential-backup]]
    - [[#sctn-automation-set-credential-properties]]
- [[#sctn-compound-attestation]]
- [[#prf-extension]]
- Registration parameter
    <code>{{CredentialCreationOptions/publicKey}}.{{PublicKeyCredentialCreationOptions/attestationFormats}}</code>:
    [[#dictionary-makecredentialoptions]]


### Editorial Changes ### {#changes-l3-editorial}

The following changes were made to improve clarity, readability, navigability and similar aspects of the document.

- Updated [[#sctn-use-cases]] to reflect developments in deployment landscape.
- Introduced [=credential record=] concept to formalize what data [=[RPS]=] need to store
    and how it relates between [=registration ceremony|registration=] and [=authentication ceremonies=].
- Clarified error conditions:
    - [[#sctn-create-request-exceptions]]
    - [[#sctn-get-request-exceptions]]
- [[#sctn-strings]] split into subsections [[#sctn-strings-truncation-client]] and [[#sctn-strings-truncation-authenticator]]
    to clarify division of responsibilities.
- Added [[#sctn-test-vectors]].
- Moved normative language outside of "note" blocks.
- Removed outdated notes about permissions policy in [[webauthn-3-20250127#sctn-isUserVerifyingPlatformAuthenticatorAvailable]]
    and [[webauthn-3-20250127#sctn-getClientCapabilities]].
- Added algorithm -8 (EdDSA) to example code in [[webauthn-3-20250127#sctn-sample-registration]].


<pre class=biblio>
{

  "UAX29": {
    "href": "http://www.unicode.org/reports/tr29/",
    "title": "UNICODE Text Segmentation",
    "publisher": "UNICODE Consortium"
  },


  "IANA-COSE-ALGS-REG": {
    "href": "https://www.iana.org/assignments/cose/cose.xhtml#algorithms",
    "title": "IANA CBOR Object Signing and Encryption (COSE) Algorithms Registry",
    "publisher": "IANA"
  },


  "WebAuthnAPIGuide": {
    "href": "https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API",
    "title": "Web Authentication API Guide",
    "publisher": "MDN: Mozilla Developer Network",
    "status": "Experimental"
  },

  "Ceremony": {
    "title": "Ceremony Design and Analysis",
    "href": "https://eprint.iacr.org/2007/399.pdf",
    "authors": ["Carl Ellison"],
    "date": "2007"
  },

  "RFC8809": {
    "authors": [
        "Jeff Hodges",
        "Giridhar Mandyam",
        "Michael B. Jones"
    ],
    "date": "August 2020",
    "href": "https://www.rfc-editor.org/rfc/rfc8809",
    "publisher": "IETF",
    "status": "IETF Proposed Standard",
    "title": "Registries for Web Authentication (WebAuthn)"
  },

  "IANA-WebAuthn-Registries": {
    "authors": [
        "IANA"
    ],
    "href": "https://www.iana.org/assignments/webauthn/",
    "title": "Web Authentication (WebAuthn) registries"
  },

  "SP800-800-63r3": {
    "title": "NIST Special Publication 800-63: Digital Identity Guidelines",
    "href": "https://pages.nist.gov/800-63-3/sp800-63-3.html",
    "authors": ["Paul A. Grassi", "Michael E. Garcia", "James L. Fenton"],
    "date": "June 2017"
  },

  "UAFProtocol": {
    "authors": ["R. Lindemann", "D. Baghdasaryan", "E. Tiffany", "D. Balfanz", "B. Hill", "J. Hodges"],
    "title": "FIDO UAF Protocol Specification v1.0",
    "status": "FIDO Alliance Proposed Standard",
    "href": "https://fidoalliance.org/specs/fido-uaf-v1.0-ps-20141208/fido-uaf-protocol-v1.0-ps-20141208.html"
  },

  "SEC1": {
    "title": "SEC1: Elliptic Curve Cryptography, Version 2.0",
    "publisher": "Standards for Efficient Cryptography Group",
    "href": "http://www.secg.org/sec1-v2.pdf"
  },

  "FIDOMetadataService": {
    "authors": ["R. Lindemann", "B. Hill", "D. Baghdasaryan"],
    "title": "FIDO Metadata Service",
    "href": "https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-metadata-service-v2.0-id-20180227.html",
    "status": "FIDO Alliance Implementation Draft",
    "date": "27 February 2018"
  },

  "FIDOU2FJavaScriptAPI": {
    "authors": ["D. Balfanz", "A. Birgisson", "J. Lang"],
    "title": "FIDO U2F JavaScript API",
    "href": "https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-javascript-api-v1.2-ps-20170411.html",
    "status": "FIDO Alliance Proposed Standard"
  },

  "TPMv2-Part1": {
    "title": "Trusted Platform Module Library, Part 1: Architecture",
    "publisher": "Trusted Computing Group",
    "href": "https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-1-Architecture-01.38.pdf"
  },

  "TPMv2-Part2": {
    "title": "Trusted Platform Module Library, Part 2: Structures",
    "publisher": "Trusted Computing Group",
    "href": "https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf"
  },

  "TPMv2-Part3": {
    "title": "Trusted Platform Module Library, Part 3: Commands",
    "publisher": "Trusted Computing Group",
    "href": "https://www.trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-3-Commands-01.38.pdf"
  },

  "TPMv2-EK-Profile": {
    "title": "TCG EK Credential Profile for TPM Family 2.0",
    "publisher": "Trusted Computing Group",
    "href": "https://trustedcomputinggroup.org/wp-content/uploads/TCG-EK-Credential-Profile-V-2.5-R2_published.pdf"
  },

  "FIDOAuthnrSecReqs": {
    "authors": ["D. Biggs", "J.E. Hill", "L. Lundblade", "M. Karlsson"],
    "title": "FIDO Authenticator Security Requirements",
    "href": "https://fidoalliance.org/specs/fido-security-requirements-v1.0-fd-20170524/",
    "status": "FIDO Alliance Final Documents"
  },

  "FIDOSecRef": {
    "authors": ["R. Lindemann", "D. Baghdasaryan", "B. Hill", "Dr. J. E. Hill", "D. Biggs"],
    "title": "FIDO Security Reference",
    "href": "https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-security-ref-v2.0-id-20180227.html",
    "status": "FIDO Alliance Implementation Draft",
    "date": "27 February 2018"
  },

  "FIDO-Registry": {
    "authors": ["R. Lindemann", "D. Baghdasaryan", "B. Hill"],
    "title": "FIDO Registry of Predefined Values",
    "href": "https://fidoalliance.org/specs/common-specs/fido-registry-v2.1-ps-20191217.html",
    "status": "FIDO Alliance Proposed Standard",
    "date": "17 December 2019"
  },

  "FIDO-APPID": {
    "authors": ["D. Balfanz", "B. Hill", "R. Lindemann", "D. Baghdasaryan"],
    "title": "FIDO AppID and Facet Specification",
    "href": "https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-appid-and-facets-v2.0-id-20180227.html",
    "status": "FIDO Alliance Implementation Draft",
    "date": "27 February 2018"
  },

  "FIDO-U2F-Message-Formats": {
    "authors": ["D. Balfanz", "J. Ehrensvard", "J. Lang"],
    "title": "FIDO U2F Raw Message Formats",
    "href": "https://fidoalliance.org/specs/fido-u2f-v1.1-id-20160915/fido-u2f-raw-message-formats-v1.1-id-20160915.html",
    "status": "FIDO Alliance Implementation Draft"
  },

  "FIDO-CTAP": {
    "authors": ["J. Bradley", "J. Hodges", "M. B. Jones", "A. Kumar", "R. Lindemann", "J. Verrept"],
    "title": "Client to Authenticator Protocol (CTAP)",
    "href": "https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html",
    "status": "FIDO Alliance Proposed Standard",
    "date": "June 21, 2022"
  },

  "FIDO-UAF-AUTHNR-CMDS": {
    "authors": ["R. Lindemann", "J. Kemp"],
    "title": "FIDO UAF Authenticator Commands",
    "href": "https://fidoalliance.org/specs/fido-uaf-v1.1-id-20170202/fido-uaf-authnr-cmds-v1.1-id-20170202.html",
    "status": "FIDO Alliance Implementation Draft"
  },

  "FIDO-Privacy-Principles": {
    "authors": ["FIDO Alliance"],
    "title": "FIDO Privacy Principles",
    "href": "https://fidoalliance.org/wp-content/uploads/2014/12/FIDO_Alliance_Whitepaper_Privacy_Principles.pdf",
    "status": "FIDO Alliance Whitepaper"
  },

  "FIDO-Transports-Ext": {
    "authors": ["FIDO Alliance"],
    "title": "FIDO U2F Authenticator Transports Extension",
    "href": "https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-authenticator-transports-extension-v1.2-ps-20170411.html",
    "status": "FIDO Alliance Proposed Standard"
  },

  "RFC8610": {
    "authors": ["H. Birkholz", "C. Vigano", "C. Bormann"],
    "title": "Concise Data Definition Language (CDDL): A Notational Convention to Express Concise Binary Object Representation (CBOR) and JSON Data Structures",
    "href": "https://tools.ietf.org/html/rfc8610",
    "status": "IETF Proposed Standard",
    "date": "June 2019"
  },

  "ISOBiometricVocabulary": {
    "authors": ["ISO/IEC JTC1/SC37"],
    "title": "Information technology — Vocabulary — Biometrics",
    "href": "http://standards.iso.org/ittf/PubliclyAvailableStandards/c055194_ISOIEC_2382-37_2012.zip",
    "status": "International Standard: ISO/IEC 2382-37:2012(E) First Edition",
    "date": "15 December 2012"
  },

  "TokenBinding": {
    "authors": ["A. Popov", "M. Nystroem", "D. Balfanz", "J. Hodges"],
    "title": "The Token Binding Protocol Version 1.0",
    "href": "https://tools.ietf.org/html/rfc8471",
    "status": "IETF Proposed Standard",
    "date": "October, 2018"
  },

  "EduPersonObjectClassSpec": {
    "publisher": "Research and Education FEDerations group - REFEDS.org",
    "title": "EduPerson",
    "href": "https://refeds.org/eduperson",
    "date": "ongoing"
  }

}
</pre>
